我一直在研究但无法在一个相当大的表(500k行)上解决这个缓慢的ORDER by子句。
我有以下查询:
SELECT gifts.gift_id, gifts.gift_title, gifts.gift_price, gifts.gift_image, gifts.gift_slug
FROM gifts
LEFT JOIN tags_gifts_occasion_specific AS os ON gifts.gift_id = os.gift_id
LEFT JOIN popularity ON popularity.gift_id = gifts.gift_id
WHERE published = '1'
AND (
os.tag_id IS NULL
)
ORDER BY popularity.popularity DESC , gift_id DESC
它可以快速(0.0007秒),直到添加 ORDER BY popular.popularity ,然后需要4.7秒!
流行度表确实有索引,但我知道这与排序无关。我只是不明白为什么这么慢。当我在同一张桌子中受欢迎时它速度很快,但我现在已将其移动到一个单独的表中,以提高性能和增强功能。
对此的任何建议都非常感激。
说明:
1 SIMPLE gifts ref index_published index_published 1 const 494384 Using where; Using temporary; Using filesort
1 SIMPLE os ref Gift ID Gift ID 4 gifts.gift_id 1 Using where; Using index; Not exists
1 SIMPLE popularity ref Unique,Index Gift ID Unique 4 gifts.gift_id 1
热门表格指数:
该表有3列,所有这些列都有自己的索引(gift_id,tag_id,popular) 此搜索中未使用标记ID 三列
还有一个UNIQUE索引Edit Drop Drop Unique BTREE Yes No gift_id 26019 A No
tag_id 26019 A No
Edit Edit Drop Drop Index Gift ID BTREE No No gift_id 26019 A No
Edit Edit Drop Drop Index Tag ID BTREE No No tag_id 3 A No
Edit Edit Drop Drop Index Popularity BTREE No No popularity 351 A No
答案 0 :(得分:1)
我很好奇当您拥有索引popularity(popularity desc, gift_id)
时,此版本的查询是如何执行的:
select g.gift_id, g.gift_title, g.gift_price, g.gift_image, g.gift_slug, p.popularity
from popularity p join
gifts g
on p.gift_id = g.gift_id
where g.published = '1' and
not exists (select 1
from tags_gifts_occasion_specific tgos
where tgos.gift_id = p.gift_id
)
order by p.popularity DESC, g.gift_id DESC;
这与您的查询不完全相同,因为没有受欢迎程度的礼品不包含在结果集中。这个版本可能会说服MySQL在popularity
上使用上述索引,其余的工作都是通过索引查找完成的。
编辑:
如果您愿意将其作为两个查询运行,则可以执行上述查询,然后:
select g.gift_id, g.gift_title, g.gift_price, g.gift_image, g.gift_slug
from gifts g
where g.published = '1' and
not exists (select 1
from tags_gifts_occasion_specific tgos
where tgos.gift_id = p.gift_id
) and
not exists (select 1
from popularity p
where p.gift_id = g.gift_i
order by g.gift_id DESC;
您甚至可以将这些与union all
合并。我有点气馁。它可能在实践中有效,但没有明确保证union all
的结果来自第一个查询后跟第二个查询。