我是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)呢?
谢谢!
答案 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
之类的查询是否会触及索引。