具有复杂MySQL查询的索引

时间:2013-07-07 13:54:41

标签: mysql optimization query-optimization

我有以下查询:

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)

或者是否有更理想的查询路径?

2 个答案:

答案 0 :(得分:0)

您建议的索引是相关的。

但是本身没有“正确”或“最佳”索引这样的东西,你需要考虑表格的完整结构以及基数。例如,is_category_valid = 1有多少记录(按比例)?如果大多数记录满足此条件,则此字段的索引几乎没用。

根本的想法是按照“重要性”的顺序包含列,也就是说首先在最具判别力的列上包含列。例如,如果大多数类别都是“有效”,我会将列is_category_valid推送到索引的末尾。

GROUP BYORDER BY条款中出现的列有例外,但您已经知道了这一点,所以看来似乎是这样的。

您应该查看查询执行计划(EXPLAIN SELECT [your query here])并查看查询的处理方式。尝试各种组合,看看哪一个表现更好。请记住,当您的数据集发展时,今天的“最佳”索引可能会变得不那么理想。

答案 1 :(得分:0)

RandomSeed有很好的观点。对于您遇到的问题,我会尝试针对您要求的最小粒度优化索引。在这种情况下,您将专门查找给定的“item_ID”..将其移动到索引的前端位置。然后我将根据结果预期的粒度再次考虑其他标准或组。你有Is_Category_Valid和Created_At ..我希望,因为大多数类别都是有效的,我会在第二个位置创建create_at。这基本上说明索引可以跳转到项目ID 3783,并在其中,转到创建日期2013-07-07(通过Date_sub减少5天)。在这一点上,我将通过索引的标准进入组,最后是有效的

index (item_id, created_at, interval_venue_id, is_category_valid )

但是,每个查询都不同,您需要查看获取粒度级别数据的最快方法...并且具有覆盖索引(如果可能),以防止需要转到原始页面数据级别也有助于加快速度。