mysql在特定阈值下获取最大值的最快方法

发布于 2024-11-05 00:15:11 字数 1275 浏览 4 评论 0原文

我在 mysql 中有两个表和一个慢速查询。

表格:

  1. 包含通道、开始时间、结束时间

  2. 字段的表格剪辑

    包含通道、开始时间、结束时间字段的表格显示

    包含通道、开始时间、结束时间

两个表都有字段 start_time 的索引。

我正在尝试查找许多剪辑中在剪辑之前开始的节目。

到目前为止,我得到了这个查询:

SELECT (
   SELECT shows.id 
   FROM shows
   WHERE shows.starttime<=clips.starttime AND shows.channel=clips.channel
   ORDER BY shows.starttime DESC
   LIMIT 1) as show_id,
   clips.*
FROM clips

对于少量的剪辑,这效果很好,但对于大量的剪辑,它变得太慢。

我的理解是,依赖子查询应该特别快,因为 start_time 上有一个索引,并且需要做的只是索引查找。尽管如此,它还是很慢,并且解释查询状态是“使用where”而不是“使用索引”。

这是解释的输出

--+------------------+-----+-----+------------+---------+------+----+------+-----------------------+
id| select_type      |table|type |possibleKeys| key     |keylen|ref |rows  | Extra                 |
--+------------------+-----+-----+------------+---------+------+----+------+-----------------------+
 1|PRIMARY           |clips|range| startDate  |startDate| 8    |NULL| 9095 |Using where;Using index|
 2|DEPENDENT SUBQUERY|shows|index| startDate  |startDate| 8    |NULL|287896|Using where;Using index|
--+------------------+-----+-----+------------+---------+------+----+------+-----------------------+

任何有关如何提高此任务性能的建议将不胜感激。

I've got two tables and a slow query in mysql.

The tables:

  1. Table clips with fields channel,start_time,end_time

  2. Table shows with fields channel,start_time,end_time

both tables have indeces for field start_time.

I am trying to find the show that started just before the clip for many clips.

So far I've got this query:

SELECT (
   SELECT shows.id 
   FROM shows
   WHERE shows.starttime<=clips.starttime AND shows.channel=clips.channel
   ORDER BY shows.starttime DESC
   LIMIT 1) as show_id,
   clips.*
FROM clips

For a small number of clips this works great but for large number of clips it gets too slow.

My understanding would be that the dependent subquery should be extra fast since there is an index on start_time and all that needs to be done is an index lookup. Nevertheless it is slow and explaining the query states "using where" instead of "using index".

Here is the output of explain

--+------------------+-----+-----+------------+---------+------+----+------+-----------------------+
id| select_type      |table|type |possibleKeys| key     |keylen|ref |rows  | Extra                 |
--+------------------+-----+-----+------------+---------+------+----+------+-----------------------+
 1|PRIMARY           |clips|range| startDate  |startDate| 8    |NULL| 9095 |Using where;Using index|
 2|DEPENDENT SUBQUERY|shows|index| startDate  |startDate| 8    |NULL|287896|Using where;Using index|
--+------------------+-----+-----+------------+---------+------+----+------+-----------------------+

Any suggestions on how to improve performace for this task would be greatly appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

不顾 2024-11-12 00:15:11

尝试将查询重写为

SELECT max(shows.starttime) as show_start, shows.id as show_id, clips.*
FROM shows
INNER JOIN clips ON (clips.channel = shows.channel AND shows.starttime<=clips.starttime)
GROUP BY clips.id

因为剪辑是节目的一部分,所以您希望它们靠近在一起,您可以通过执行以下操作进一步限制命中数:

SELECT max(shows.starttime) as show_start, shows.id as show_id, clips.*
FROM shows
INNER JOIN clips ON (clips.channel = shows.channel 
  AND clips.starttime BETWEEN shows.starttime AND DATE_ADD(shows.starttime, INTERVAL 1 DAY) )
GROUP BY clips.id

这将阻止 MySQL 运行对每一行进行排序的完整子查询的剪辑。

Try to rewrite the query as

SELECT max(shows.starttime) as show_start, shows.id as show_id, clips.*
FROM shows
INNER JOIN clips ON (clips.channel = shows.channel AND shows.starttime<=clips.starttime)
GROUP BY clips.id

Because clips are part of a show, you would expect them to be close together, you can limit the number of hits further by doing something like:

SELECT max(shows.starttime) as show_start, shows.id as show_id, clips.*
FROM shows
INNER JOIN clips ON (clips.channel = shows.channel 
  AND clips.starttime BETWEEN shows.starttime AND DATE_ADD(shows.starttime, INTERVAL 1 DAY) )
GROUP BY clips.id

This will prevent MySQL from running a full subquery with sort on every row of clips.

一人独醉 2024-11-12 00:15:11

我认为添加同时使用 start_timechannel 列的索引可能会将查询性能提高到可接受的值。

约翰的回答很好,但考虑到你的过滤器,我认为索引在任何情况下都可以提高性能。

I think adding an index that uses both start_time and channel columns may improve the query performance to an acceptable value.

Johan's answer is great, but given your filters I think the index may improve the performance in any case.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文