具有复杂 MySQL 查询的索引
Posted
技术标签:
【中文标题】具有复杂 MySQL 查询的索引【英文标题】:Index with a Complex MySQL Query 【发布时间】:2013-07-07 13:54:40 【问题描述】:我有以下疑问:
SELECT venues.venue_name, count( distinct checkin.user_id ) AS total_count, category_id
FROM checkin
INNER JOIN venues ON checkin.internal_venue_id = venues.venue_primary_id
WHERE checkin.item_id = '3783'
and is_category_valid = 1 and created_at >= DATE_SUB('2013-07-07 12:35:06', INTERVAL 5 DAY)
GROUP BY checkin.internal_venue_id
ORDER BY total_count DESC
LIMIT 10;
我正在努力处理此查询所需的索引。是否正确的索引:
checkin: (internal_venue_id, item_id, is_category_valid, created_at, user_id)
或者还有其他更理想的查询路径吗?
【问题讨论】:
【参考方案1】:您建议的索引是相关的。
但没有“正确”或“最佳”索引本身这样的东西,您需要考虑表的完整结构以及基数。例如,is_category_valid = 1
有多少条记录(按比例)?如果大多数记录都满足这个条件,那么这个字段上的索引就没什么用了。
基本思想是按“重要性”的顺序包含列,也就是说,首先在最具辨别力的列上。例如,如果大多数类别都是“有效的”,我会将 is_category_valid
列推到索引的末尾。
(出现在GROUP BY
和ORDER BY
子句中的列有一个例外,但你已经知道了,所以看起来)
您应该查看查询执行计划 (EXPLAIN SELECT [your query here]
) 并查看查询是如何处理的。尝试各种组合,看看哪一种表现更好。请记住,随着数据集的发展,今天的“最佳”索引可能会变得不太理想。
【讨论】:
【参考方案2】:RandomSeed 有很好的优点。但是,对于您遇到的情况,我会尝试在您所要求的最小粒度上优化索引。在这种情况下,您正在专门寻找给定的“item_ID”.. 将其移动到索引的前面位置。然后,我将有其他标准或分组作为下一个考虑因素……再次,基于结果预期的粒度。你有 Is_Category_Valid 和 Created_At.. 我希望因为大多数类别都是有效的,所以我会在第二个位置创建 created_at。这基本上是说明索引可以跳转到项目 ID 3783,并在其中转到创建日期 2013-07-07(通过 Date_sub 减少 5 天)。在这一点上,我将在 group by 索引的标准中通过,最后是 Valid
index (item_id, created_at, interval_venue_id, is_category_valid )
但是,每个查询都是不同的,您确实需要寻找最快的方法来获取粒度级别的数据......并拥有一个覆盖索引(如果可能),以防止需要进入原始页面数据级别也有助于加快速度。
【讨论】:
所以您不会将 user_id 作为索引的一部分? @gregavola,对不起,把它放在最后,因为它只是你想要的一个“额外”列,并且对于查询中的 where 或 group by / order by 条件没有任何好处。 是的,但我按该列的计数(不同的 user_id)排序。这个范围应该很高吗? @gregavola,如果您期望给定场地有很多不同的“user_id”值,那么我会在索引的“is_category_valid”部分之前有该列以上是关于具有复杂 MySQL 查询的索引的主要内容,如果未能解决你的问题,请参考以下文章