该说明表明您未在表phpfox_channel_video as m
上使用索引,并且正在表phpfox_channel_category AS mc
上使用临时索引,这意味着它没有在使用索引,而是在构建一个首先进行索引,这需要花费大量时间。
此外,表phpfox_channel_category_data AS mcd
的索引可能更好。
您需要的索引是:
CREATE INDEX idx_cat_data_video_id ON phpfox_channel_category_data
(category_id,video_id);
CREATE INDEX idx_channel_cat_id ON phpfox_channel_category (category_id);
CREATE INDEX idx_video_mult ON phpfox_channel_video
(in_process,view_id,module_id,item_id,privacy,video_id,time_stamp);
,
->(类似)
AND EXISTS(
SELECT 1
FROM phpfox_channel_category AS mc
JOIN phpfox_channel_category_data AS mcd
ON mcd.video_id = mc.video_id
WHERE mcd.video_id = 17
AND mc.video_id = m.video_id
)
,
让我们确保我们正在优化正确的查询。我建议我们在ON
子句中检查这种情况:
mc.category_id = mc.category_id
我们知道mc
中的每一行都将为TRUE,且其非空值为category_id
。我们可以将该条件表示为:
mc.category_id IS NOT NULL
这意味着联接几乎是交叉联接; m
返回的每一行都与mc
返回的每一行匹配。也就是说,我们可以得到等效的结果:
FROM phpfox_channel_video m
JOIN phpfox_channel_category mc
ON mc.category_id IS NOT NULL
我怀疑这不是我们追求的结果。我认为我们的意思是匹配m.category_id
。但这只是一个猜测。
如果video_id
列是m
上的PRIMARY KEY或UNIQUE KEY,则可以通过使用带有相关子查询的EXISTS来避免创建重复行的联接,从而避免潜在的昂贵GROUP BY
操作。如果我们可以避免生成具有重复值video_id
的中间结果,那么就可以避免需要执行GROUP BY
。
此外,对于内联视图查询,我们可以只返回所需的表达式,而不是返回所有列*
。在外部查询中,唯一引用的列是user_id
。
所以我们可以这样写:
SELECT COUNT(*) AS total_rows
FROM (
SELECT m.user_id
FROM phpfox_channel_video m
WHERE EXISTS ( SELECT 1
FROM phpfox_channel_category mc
WHERE mc.category_id = m.category_id
-- mc.category_id = mc.category_id -- <original
)
AND EXISTS ( SELECT 1
FROM phpfox_channel_category_data mcd
WHERE mcd.video_id = m.video_id
AND mcd.category_id = 17
)
AND m.in_process = 0
AND m.view_id = 0
AND m.module_id = 'videochannel'
AND m.item_id = 0
AND m.privacy IN (0)
ORDER BY m.time_stamp DESC
LIMIT 12
) d
JOIN phpfox_user u
ON u.user_id = d.user_id
为了进行调整,m
的最佳索引将包含具有相等谓词的前导列,其后是time_stamp
列,这样我们就可以避免执行“使用文件排序”操作,ORDER BY
可以通过按索引顺序返回行来满足。看来我们需要对行进行排序的原因是为了LIMIT子句。
... ON phpfox_channel_video (in_process,time_stamp,... )
另外两个表,我们希望索引的前导列具有相等谓词
... ON phpfox_channel_category_data (video_id,category_id,...)
... ON phpfox_channel_category ( category_id,... )
注意:
(尚不清楚为什么我们需要内联视图,并且我们延迟了user_id
引用的联接。然后,整个查询的重点对我来说并不很明显;我是只是根据给定的SQL提供了对条件category_id
的更改的重写。)
以上假设category_id
中存在m
列,并且它是一对多关系。
但是如果这不是真的...如果mcd
表实际上是联结表,则解决了视频和类别之间的多对多关系,因此联接条件本来应该是
mcd.category_id = mc.category_id
^
然后,我们希望将上面查询中的WHERE EXISTS
和AND EXISTS
替换为单个相关子查询。像这样:
SELECT COUNT(*) AS total_rows
FROM (
SELECT m.user_id
FROM phpfox_channel_video m
WHERE EXISTS ( SELECT 1
FROM phpfox_channel_category mc
JOIN phpfox_channel_category_data mcd
ON mcd.category_id = mc.category_id
WHERE mcd.video_id = m.video_id
AND mcd.category_id = 17
)
AND m.in_process = 0
AND m.view_id = 0
AND m.module_id = 'videochannel'
AND m.item_id = 0
AND m.privacy IN (0)
ORDER BY m.time_stamp DESC
LIMIT 12
) d
JOIN phpfox_user u
ON u.user_id = d.user_id
本文链接:https://www.f2er.com/3107774.html