综合指数

时间:2013-06-03 20:31:14

标签: mysql indexing composite-index

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

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

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

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是否为空”符合条件以使这些查询使用复合索引。

  • 您对什么是最好的(综合指数或2个指数)有什么想法?我试图用“解释”来弄清楚什么是最好的,但我不确定如何解释结果。

  • 更一般地说:对于在(column1,column2)上有一个复合索引的表,我知道对column2的过滤只会不使用索引。 但是,如果我在这样做的时候引入虚拟条件(如column1&gt; MIN_VALUE)或(column1不为null)呢?

谢谢!

2 个答案:

答案 0 :(得分:1)

如果您删除了用户提到的空值。复合索引可能适用于第一个查询。

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

通常它按索引中的Left-Most列并按此顺序排列。

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

的开销(可能是)

答案 1 :(得分:1)

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

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

相反,只有在最左侧的列涉及搜索条件或as the manual puts it时才能使用复合索引:

  

MySQL可以对测试所有内容的查询使用多列索引   索引中的列,或仅测试第一列的查询,   前两列,前三列,依此类推

关于你建议的hack(引入虚拟条件以便能够使用索引),这可能有用,但我宁愿建议仅在column2上创建第二个索引(除了两列之外) (column1, column2)上的索引。这是一个(次要)成本,但更优雅和可重复使用。

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

另一方面,性能提升是可疑的(我相信这主要是基于NULL未编入索引的错误假设)。如果存在这样的索引,很容易验证s.completed_time IS NOT NULL之类的查询是否会触及索引。