繁体   English   中英

使用ORDER BY时Painfull缓慢的MySQL查询(并建立索引)

[英]Painfull slow MySQL query when using ORDER BY (And indexed)

我一直在研究,但无法在一个相当大的表(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 Popularity.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,流行度)。在此搜索中未使用标签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  

我很好奇这个版本的查询在索引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来自第一个查询,然后是第二个查询。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM