我有一个以 innodb 作为存储引擎的 MySQL 数据库,并且我有许多采用基本形式的查询:
SELECT bd.billing,
SUM(CASE WHEN tc.transaction_class = 'c' THEN bd.amount ELSE 0 END) AS charges,
SUM(CASE WHEN tc.transaction_class = 'a' THEN bd.amount ELSE 0 END) AS adjustments,
SUM(CASE WHEN tc.transaction_class = 'p' THEN bd.amount ELSE 0 END) AS payments,
SUM(bd.amount) AS balance_this_month
FROM billing_details bd
JOIN transaction_classes tc ON tc.transaction_code = bd.transaction_code
WHERE bd.entry_date BETWEEN '2013-06-04' AND '2013-07-01'
GROUP BY billing;
我正在尝试制定为采用这种形式的查询的列编制索引的最佳策略。在我开始之前,只有单个列上的索引,并且解释显示正在读取 150 万行(因为,正如您在此处看到的,只有一个月的数据价值)。
我的第一次尝试将这个数字降低到 ~300,000,这是通过索引(entry_date、billing、transaction_code)实现的。在做了更多阅读(特别是高性能 MySQL)之后,我决定将 entry_date(通常是一个范围表达式)作为我最左边的列并不是最优的,所以我尝试了 (billing, transaction_code, entry_date) 并解释显示更像 4 -500,000 行。仍然比第一个数字有所改进,但随着我深入挖掘,我开始怀疑:
对于此类查询,我可以合理地期望从最佳索引中得到什么?我猜,因为我正在执行一个聚合函数,它总是会构建一个临时表并进行文件排序......或者是吗?我读得越多,我就越困惑。我的直觉是使用 entry_date 作为最左边的列,因为它是我的 where 子句中的唯一规定。更多的研究让我相信我应该把它放在最正确的位置,因为我正在查询一系列日期。但是我读到的只是真正谈论 where 子句——它只有 entry_date:这样的 sum/case 查询呢?我是否可以以有益的方式向该索引添加数量,或者除非我重新设计架构/查询,否则我是否会被我所拥有的东西所困扰?