mysql - 综合指数

标签 mysql indexing composite-index

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

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

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

  • 更一般地说:对于在 (column1, column2) 上具有复合索引的表,我知道仅在 column2 上进行过滤不会使用该索引。 但是,如果我引入一个虚拟条件,例如 (column1 > MIN_VALUE),或者(column1 不为空),当这样做是正确的时候会怎样?

谢谢!

最佳答案

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

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

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

MySQL can use multiple-column indexes for queries that test all the columns in the index, or queries that test just the first column, the first two columns, the first three columns, and so on

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

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

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

关于mysql - 综合指数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16905323/

相关文章:

ruby - DataMapper 属性可以出现在多个复合索引中吗?

php - 优化此查询,从具有 500.000 个用户和一个条件的 MySQL 数据库中检索用户

php - 执行后更改php文件

mysql - 执行mysql转储文件以在nodejs项目中创建表并提供数据

python - Pandas DataFrame 中值函数

mysql - 慢查询,state = 'Sorting result' mysql

python - Numpy 索引,获取宽度为 2 的 strip

firebase - 在 firestore [通配符] 中为点注释动态路径创建索引?

mysql - "Using index",复合索引 : A=, B=, C<=

mysql - ruby:从字符串中去除反斜杠