我有一个简单的历史表,我正在开发一个新的查找。我想知道添加到此表的最佳索引(如果有的话)是什么,以便查找尽可能快。
历史记录表是一组简单的操作记录。每个操作都有一个类型和一个操作日期(以及一些其他属性)。系统每天都会生成一组新的操作记录。
相关的伪模式是:
TABLE history
id int,
type int,
action_date date
...
INDEX
id
...
注意:该表格未已在type
或action_date
上编入索引。
新的查找功能旨在检索特定操作日期发生的特定类型的所有记录。
我最初的倾向是定义一个由type
和action_date
组成的复合键。
但是在我的情况下,会有许多具有相同类型和日期的动作。此外,每天的行动数量大致均匀分布。
考虑到以上所有因素:(a)是一个值得的指数; (b)如果是,那么首选指数是什么?
我正在使用MySQL,但我认为我的问题不是特定于此RDBMS。
答案 0 :(得分:1)
索引上的第一个字段应该是在应用条件后为大多数查询提供最小数据集的字段。
根据您的业务要求,您可以申请特定日期或特定日期范围(很可能是日期范围)。所以日期应该是索引上的最后一个字段。很可能你总是会有日期条件。
一个常见的答案是拥有(类型,日期)索引,但如果您在查询中查询了多个类型值,或者只有少数类型(如少于5个),则应该只考虑日期索引)并且它们不是均匀分布的。
例如,你有类型1 70%的表,类型2,3,4,...小于表的百分之几,而你经常查询类型1,你最好只有单独的日期索引,和类型索引(对于查询类型2,3,4时的情况),而不是复合(类型,日期)索引。
答案 1 :(得分:1)
INDEX(type, action_date)
,无论任何列的基数或分布如何。这样做可以最大限度地减少'行的数量。需要查看的索引的BTree` (是的,我不同意Sergiy的答案。)
即使WHERE type IN (2,3) AND action_date ...
也可以使用该索引。
为了检查日期范围,例如2周,我推荐这种模式:
AND action_date >= '2016-10-16`
AND action_date < '2016-10-16` + INTERVAL 2 WEEK
一种了解多少&#34;工作&#34;查询需要:
FLUSH STATUS;
SELECT ...;
SHOW SESSION STATUS LIKE 'Handler%';
显示的数字将让您了解需要触摸多少个索引(或数据)行。这使得很容易看出两个可能的查询/索引中哪一个更好,即使表太小而无法获得可靠的时序。
答案 2 :(得分:0)
是的,索引是值得的。特别是如果您搜索表的一小部分。
如果您的搜索匹配表的大约20%或更多(大约),MySQL优化器会确定索引比它的价值更麻烦,即使索引可用,它也会进行表扫描。 / p>
如果搜索一个特定type
值和一个特定date
值,则(类型,日期)上的索引或(日期,类型)上的索引是一个不错的选择。您首先列出哪一列并不重要。
如果您搜索多个类型的值或多个日期,则列的顺序很重要。请遵循以下指南:
索引最左边的列应该是您进行相等比较的列。相等比较恰好匹配一个值(即使在很多行上找到该值)。
WHERE type = 2 AND date = '2016-10-19' -- both equality
索引的下一列可以是范围比较的一部分。范围比较匹配多个值。例如,>
或IN( )
或BETWEEN
或!=
。
WHERE type = 2 AND date > '2016-10-19' -- one equality, one range
只有一个这样的列才能从索引中受益。如果您对多列进行范围比较,则只有索引的第一列将使用索引来支持查找。后续的列必须“艰难地”搜索那些匹配的行。
WHERE type IN (2, 3, 4) AND date > '2016-10-19' -- multiple range
如果您有时使用type
上的范围条件和date
上的相等进行搜索,则需要创建第二个索引。
WHERE type IN (2, 3, 4) AND date = '2016-10-19' -- make index on (date, type)
WHERE
子句中的术语顺序无关紧要。 SQL查询优化器将计算出来并重新排序它们以匹配索引中定义的右列。