1

我是 MySQL 新手,我需要在现有表(包含大约 200K 行)上添加索引。

Table mytable: (id:integer, created_time:timestamp, deleted_time:timestamp)

我有 2 个查询需要从索引中受益:

select s.id from mytable s
where s.completed_time is not null
and s.completed_time < ?
and ( s.deleted_time is null
    or s.deleted_time >= ? );

和 :

select s.id from mytable s 
where
   s.completed_time is not null 
and (
   ( s.deleted_time is not null 
   and s.deleted_time >= ? 
   and s.deleted_time < ? )
 or ( s.completed_time >= ? 
   and s.completed_time < ? ) ) ;

我正在考虑引入多列索引(在 completed_time 和 deleted_time 上)但是,我不确定条件“s.completed_time is not null”是否符合使这些查询使用复合索引的条件。

  • 您对什么是最好的(复合索引或 2 个索引)有任何想法吗?我正在尝试使用“解释”来找出最好的方法,但我不确定如何解释结果。

  • 更一般地说:对于(column1,column2)上具有复合索引的表,我知道仅对column2进行过滤不会使用索引。但是,如果我在正确的情况下引入类似 (column1 > MIN_VALUE) 或 (column1 is not null) 的虚拟条件会怎样?

谢谢!

4

2 回答 2

1

假设您提到的两个查询将“经常”使用,我建议使用复合索引而不是两列上的两个不同索引。

如您所知,搜索两列的查询有时可能会使用两个单独的索引,方法是(大致)将这两个索引合并为一个。但这是次优的,并且在性能方面有成本。

相反,只有在最左边的列涉及 seach 条件时,或者如手册所述,才能使用复合索引:

MySQL 可以将多列索引用于测试索引中所有列的查询,或者只测试第一列、前两列、前三列等的查询

关于您建议的技巧(引入虚拟条件以便能够使用索引),这可能有效,但我宁愿建议column2仅在上创建第二个索引(除了上的双列索引(column1, column2))。这需要(少量)成本,但更加优雅和可重用。

至于摆脱NULL价值观的建议,我强烈反对。使用 .在语义上是不正确的00意思是“零”,NULL意思是“没有价值”。您的所有测试都需要考虑这个特殊值,而这IS NULL是标准的并且在任何地方都很好理解。在某些情况下也是不切实际的(尝试用 插入0SQL_MODE='TRADITIONAL'

另一方面,性能增益是值得怀疑的(我相信这主要是基于NULL值没有被索引的错误假设)。s.completed_time IS NOT NULL如果存在这样的索引,则很容易验证类似查询是否会命中索引。

于 2013-06-04T12:04:32.573 回答
1

前提是您摆脱了用户提到的空值。复合索引可能适用于第一个查询。

但是第二个查询索引可能不起作用。- 因为它在您的索引列之间有一个 OR。

通常它按索引中最左边的列并按该顺序排列。

我建议创建单独的索引。虽然它有http://dev.mysql.com/doc/refman/5.0/en/index-merge-optimization.html的开销(可能是)

于 2013-06-03T20:59:36.107 回答