Mysql 对于一组历史记录,什么是性能最好的表索引?

Mysql 对于一组历史记录,什么是性能最好的表索引?,mysql,sql,performance,indexing,Mysql,Sql,Performance,Indexing,我有一个简单的历史表,我正在开发一个新的查找。我想知道什么是最好的索引(如果有的话)添加到这个表,以便查找尽可能快 历史记录表是一组简单的操作记录。每个操作都有一个类型和一个操作日期(以及一些其他属性)。每天系统都会生成一组新的操作记录 相关的伪模式是: TABLE history id int, type int, action_date date ... INDEX id ... 注意:该表未按类型或操作日期编制索引 新的查找功能旨在检索在特

我有一个简单的历史表,我正在开发一个新的查找。我想知道什么是最好的索引(如果有的话)添加到这个表,以便查找尽可能快

历史记录表是一组简单的操作记录。每个操作都有一个类型和一个操作日期(以及一些其他属性)。每天系统都会生成一组新的操作记录

相关的伪模式是:

TABLE history
    id int,
    type int,
    action_date date
    ...
INDEX
    id
    ...
注意:该表未按
类型
操作日期
编制索引

新的查找功能旨在检索在特定操作日期发生的特定类型的所有记录

我最初倾向于定义一个由
类型
操作日期
组成的复合键

然而,在我的案例中,将有许多相同类型和日期的操作。此外,每天的行动数量将大致均匀分布

鉴于上述所有情况:(a)是否值得建立一个指数;(b)如果是,首选指数是什么


我使用的是MySQL,但我认为我的问题并不特定于此RDBMS。

索引上的第一个字段应该是在应用条件后,为大多数查询提供最小数据集的字段

根据您的业务需求,您可以请求特定日期或特定日期范围(最有可能是日期范围)。因此,日期应该是索引上的最后一个字段。最有可能的是,您将始终具有日期条件

一个常见的答案是拥有(type,Dead)索引,但是如果你在查询中查询了不止一个类型值或者如果只有几个类型(比如小于5)并且它们不均匀分布,则应该只考虑日期索引。 例如,您有表格70%的类型1,类型2,3,4,。。。不到表的百分之几,并且您经常查询类型1,您最好只使用单独的日期索引和类型索引(对于查询类型2、3、4的情况),而不是复合(类型、日期)索引。

索引(类型、操作日期)
,而不考虑任何列的基数或分布。这样做将最大限度地减少索引的BTree`中需要查看的'行'数量。(是的,我不同意塞尔吉的回答。)

即使对于
中的键入(2,3)和操作日期…
也可以使用该索引

对于检查日期范围(例如2周),我建议使用以下模式:

AND action_date >= '2016-10-16`
AND action_date  < '2016-10-16` + INTERVAL 2 WEEK

显示的数字将让您感觉需要触摸多少索引(或数据)行。这样就可以很容易地看出两个可能的查询/索引中哪一个工作得更好,即使表太小,无法获得可靠的计时。

是的,索引是值得的。尤其是搜索表的一小部分时

如果您的搜索将匹配表的20%或更多(大约),MySQL优化器会认为索引比它的价值更麻烦,即使索引可用,它也会进行表扫描

如果搜索一个特定的
type
值和一个特定的
date
值,则在(type,date)上建立索引或在(date,type)上建立索引是一个不错的选择。首先列出哪一列并不重要

如果搜索多个类型值或多个日期值,则列的顺序很重要。请遵循以下指南:

  • 索引最左边的列应该是进行相等比较的列。相等比较是与一个值完全匹配的比较(即使在多行中找到该值)

  • 索引的下一列可以是范围比较的一部分。范围比较匹配多个值。例如,
    在()
    之间=

    WHERE type = 2 AND date > '2016-10-19' -- one equality, one range
    
    只有一个这样的列从索引中受益。如果对多列进行范围比较,则只有索引的第一列将使用索引来支持查找。后续列将不得不“艰难地”搜索那些匹配的行

  • 如果有时在
    type
    上使用范围条件,在
    date
    上使用相等条件进行搜索,则需要创建第二个索引

    WHERE type IN (2, 3, 4) AND date = '2016-10-19' -- make index on (date, type)
    
    WHERE
    子句中的术语顺序无关紧要。SQL查询优化器将对此进行计算并重新排序,以匹配索引中定义的正确列


在(类型,行动日期)(和/或(行动日期,类型))上的索引似乎是敏感的。我会在日期+类型上使用复合索引。聚类因子将非常好,因为数据似乎是按日期排序的,所以我希望它能很好地工作。不过,您必须对其进行测试,如果具有相同日期和类型的数据量非常大,则索引可能必须查找大量节点。如果复合索引工作正常,您还可以选择仅索引扫描,方法是将要选择的其他字段添加到索引中。这样,db就不需要从实际表中获取它们。(但我想这是另一个主题)您可以按类型或日期使用一些表分区。这将为查询带来一些速度@valicu2000-在这种情况下,合适的索引似乎是可行的。因此,分区不太可能提高性能。如果Date是索引中的第一个或唯一字段,则索引b树将以最坏情况平衡结束,因为历史总是添加在末尾。如果可能,最好使用。同样,(type,date)是此类讨论中常见的答案,但如果type值覆盖了超过30%的记录,则mysql不会使用索引,即使您的日期范围与第二个字段一样小。也许为了改进您的答案,您应该提到,应经常重新索引按日期索引的历史表。John,我认为总是在末尾添加更晚的日期值是增加索引的一种“自然”方式,而且永远不需要重新编制索引。但对于(type,date),类型值为un
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
WHERE type IN (2, 3, 4) AND date = '2016-10-19' -- make index on (date, type)