这就是整个查询…
SELECT s.*, (SELECT url FROM show_medias WHERE show_id = s.id AND is_primary = 1) AS media_url FROM (shows As s) WHERE `s`.`id` IN ( SELECT DISTINCT st.show_id FROM show_time_schedules AS sts LEFT JOIN show_times AS st ON st.id = sts.show_time_id WHERE sts.schedule_date BETWEEN CAST('2012-01-10' AS date) AND CAST('2012-01-14' AS date) ) AND `s`.`is_active` = 1 ORDER BY s.name asc
如果…
SELECT url FROM show_medias WHERE show_id = s.id AND is_primary = 1 (0.0004 sec)
和…
SELECT DISTINCT st.show_id FROM show_time_schedules AS sts LEFT JOIN show_times AS st ON st.id = sts.show_time_id WHERE sts.schedule_date BETWEEN CAST('2012-01-10' AS date) AND CAST('2012-01-14' AS date) (0.0061 sec)
有明显的理由吗?
SELECT s.*, (inner query 1) AS media_url FROM (shows As s) WHERE `s`.`id` IN ( inner query 2 ) AND `s`.`is_active` = 1 ORDER BY s.name asc
正在服用5.7245 sec?
5.7245 sec
扩展说明
id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY s ALL NULL NULL NULL NULL 151 100.00 Using where; Using filesort 3 DEPENDENT SUBQUERY sts ALL NULL NULL NULL NULL 26290 100.00 Using where; Using temporary 3 DEPENDENT SUBQUERY st eq_ref PRIMARY PRIMARY 4 bvcdb.sts.show_time_id 1 100.00 Using where 2 DEPENDENT SUBQUERY show_medias ALL NULL NULL NULL NULL 159 100.00 Using where
您可以始终使用EXPLAIN或EXPLAIN EXTENDED来查看MySql对查询所做的操作
您也可以用稍微不同的方式编写查询,是否尝试过以下方法?
SELECT s.*, sm.url AS media_url FROM shows AS s INNER JOIN show_medias AS sm ON s.id = SM.show_id WHERE `s`.`id` IN ( SELECT DISTINCT st.show_id FROM show_time_schedules AS sts LEFT JOIN show_times AS st ON st.id = sts.show_time_id WHERE sts.schedule_date BETWEEN CAST('2012-01-10' AS date) AND CAST('2012-01-14' AS date) ) AND `s`.`is_active` = 1 AND sm.is_primary = 1 ORDER BY s.name asc
看看效果如何会很有趣。我希望它会更快,因为目前,我认为MySql将为您拥有的每个节目运行内部查询1(这样一个查询将运行多次。联接应该更有效。)
如果希望所有show_medias中没有一行的节目,请用LEFT JOIN替换INNER JOIN。
编辑:
我将在短期内查看您的EXPLAIN EXTENDED,我也想知道您是否想尝试以下方法?它删除所有子查询:
SELECT DISTINCT s.*, sm.url AS media_url FROM shows AS s INNER JOIN show_medias AS sm ON s.id = SM.show_id INNER JOIN show_times AS st ON (s.id = st.show_id) RIGHT JOIN show_time_schedules AS sts ON (st.id = sts.show_time_id) WHERE `s`.`is_active` = 1 AND sm.is_primary = 1 AND sts.schedule_date BETWEEN CAST('2012-01-10' AS date) AND CAST('2012-01-14' AS date) ORDER BY s.name asc
(也可以在这些内容上看到扩展的扩展-您可以将其添加到此注释的注释中)。
进一步编辑:
在您的扩展说明中(这里是如何阅读这些内容的良好开端)
USING FILESORT和USING TEMPORARY都是关键指标。希望我建议的第二个查询应该删除任何TEMPORARY表(在子查询中)。然后尝试关闭ORDER BY以查看是否有区别(我们可以将其添加到到目前为止的发现中:-)
我还可以看到,很多索引查找都可能丢失查询;您所有的id列都是索引匹配的主要候选对象(具有常见的索引警告)。我还将尝试添加这些索引,然后再次运行EXPLAIN EXTENDED来查看现在的区别(编辑,正如我们从您上面的评论中已经知道的那样!)