据我理解,如果在一个只包含少量不同值的列上设置索引,你不会得到太多好处。
我有一列保存布尔值(实际上是小整数,但我将其用作标志),并且这个列在我大部分查询的WHERE
子句中都被使用。
在一个理论上的“平均”情况下,一半的记录值将是1,另一半是0。
因此,在这种情况下,数据库引擎可以避免全表扫描,但仍需要读取很多行(总行数/2)。
那么,我应该将这个列设为索引吗?
我使用的是Mysql 5,但我更感兴趣的是关于为什么对一个已知基数较低的列进行索引或不进行索引的一般性原则。
据我理解,如果在一个只包含少量不同值的列上设置索引,你不会得到太多好处。
我有一列保存布尔值(实际上是小整数,但我将其用作标志),并且这个列在我大部分查询的WHERE
子句中都被使用。
在一个理论上的“平均”情况下,一半的记录值将是1,另一半是0。
因此,在这种情况下,数据库引擎可以避免全表扫描,但仍需要读取很多行(总行数/2)。
那么,我应该将这个列设为索引吗?
我使用的是Mysql 5,但我更感兴趣的是关于为什么对一个已知基数较低的列进行索引或不进行索引的一般性原则。
即使在低基数字段上,索引也可以有所帮助,如果:
当其中一个可能值与其他值相比非常少见,并且您搜索它时。
例如,色盲女性非常少,因此这个查询:
SELECT *
FROM color_blind_people
WHERE gender = 'F'
在这种情况下,gender
上建立索引可能会带来最大的收益。
当值倾向于按表顺序分组时:
SELECT *
FROM records_from_2008
WHERE year = 2010
LIMIT 1
尽管这里只有 3
个不同的年份,但是由于较早年份的记录很可能是先添加的,如果没有索引,就需要扫描很多记录才能返回第一个 2010
记录。
当你需要进行 ORDER BY / LIMIT
操作时:
SELECT *
FROM people
ORDER BY
gender, id
LIMIT 1
如果没有索引,就需要进行文件排序filesort
。尽管由于有LIMIT
所以它在一定程度上进行了优化,但仍然需要完全扫描表。
当索引覆盖了查询中使用的所有字段:
CREATE INDEX (low_cardinality_record, value)
SELECT SUM(value)
FROM mytable
WHERE low_cardinality_record = 3
当需要使用DISTINCT
时:
SELECT DISTINCT color
FROM tshirts
MySQL
将使用INDEX FOR GROUP-BY
,如果颜色较少,则即使有数百万条记录,此查询也会立即完成。
这是一个场景的示例,在低基数字段上的索引比高基数字段上的索引更有效率。
请注意,如果DML
性能不是问题,那么创建索引是安全的。
如果优化器认为索引效率低下,那么该索引将不被使用。
将布尔字段包含在复合索引中可能是值得的。例如,如果您有一个大型消息表格,通常需要按日期排序,但还有一个布尔已删除字段,因此经常这样查询:
SELECT ... FROM Messages WHERE Deleted = 0 AND Date BETWEEN @start AND @end
在Deleted和Date字段上创建一个复合索引,可以让你受益匪浅。
当一半的记录值为1,另一半为0时,在该列上创建索引是没有意义的。查询优化器很可能不会使用它。
通常情况下,您有一个小的“活动”记录集和一个越来越大的“非活动”记录集。例如,在错误跟踪系统中,您关心活动错误,几乎不看已完成和存档的错误。对于这种情况,技巧是使用“dateInactivated”列来存储记录被停用/删除的时间戳。正如名称所示,在记录处于活动状态时,该值为NULL,但一旦停用,则写入系统日期时间。因此,在该列上创建的索引最终具有高选择性,因为“已删除”记录数增加,每个记录将具有唯一(严格来说不是)的值。查询将具有:
"... AND dateInactivated is NULL ..."
通常我会进行一个简单的“有索引”与“没有索引”的测试。根据我的经验,对于使用 ORDER BY 索引列的查询,大部分性能都可以得到提升。如果该列上存在排序,那么索引很可能会有所帮助。
在我看来,这个标记的用途有限。我假设在大多数情况下,您在查询中使用的其他标准可能会更有帮助。
如果达到50%,我可能会进行一些基准测试,看看是否有很大的差别。
where x =
而不是where x between
)时,通常期望(high, low)表现更好。 - okdewitINDEX(continent, date)
和WHERE continent='Europe' AND date BETWEEN...
只需要触及与之相关的行(在索引的BTree中)。也就是说,无论日期范围如何,都不需要“丢弃”任何内容。 - Rick James