Mysql:前缀索引与索引

时间:2015-07-20 21:25:21

标签: mysql indexing innodb

可以像普通索引一样使用mysql前缀索引吗?

如果有一些TEXT列,则前缀索引的长度为例如1,查询是:

SELECT * FROM table WHERE textcol = 'ab'

它会给我所有以'a'开头的行还是会检查整列值?

一般来说,我很想知道在使用前缀索引时是否有任何警告。不考虑性能,如果任何查询必须以不同方式编写,或者客户端是否必须执行额外的逻辑,则更多。

2 个答案:

答案 0 :(得分:5)

如果你想一下,MySQL仍会给你正确的答案,即使没有索引......它只是赢得了那么快......所以,是的,您仍然可以使用前缀索引获得正确的答案。

性能会降低,因为在匹配"可能"具有索引的行,服务器将转到行数据并进一步根据WHERE子句筛选结果。两个步骤而不是一个,但应用程序无需关心。

注意事项包括以下事实:优化器不会使用前缀索引进行某些操作,例如排序或分组,因为它没有为这些目的覆盖足够的列数据。

前缀索引的排序超出了前缀的长度。如果您的查询使用完整索引来查找行,您通常会发现返回的行是按索引顺序隐式排序的。如果您的应用程序需要这种行为,那么它当然期望它不应该期望的东西,因为除非您明确ORDER BY,否则返回行的顺序是未定义的。在任何查询中都不要依赖巧合行为,因为不仅前缀索引匹配的行不一定是任何特定的顺序......但事实上,排序不明确的任何结果集的顺序随时可能更改。

并且,前缀索引不能用作覆盖索引。覆盖索引是指SELECT中的所有列碰巧一起包含在一个索引中的情况(加上可选的主键,因为它也总是在那里)。优化器将直接从索引读取数据,而不是使用索引来标识要在主表数据中查找的行。即使索引不能用于查找匹配的行,优化器也只会对覆盖索引进行全扫描,而不是对整个表进行全扫描,从而节省了I / O和时间。 (顺便说一句,此功能应该足以让您选择所需的列,而不是懒惰的SELECT * - 它可能会打开一些更有效的查询计划)。也不能使用前缀索引。

但是除了性能,优化和查询隐含地执行您期望的事情(您不应该期待)之外,没有与前缀索引一起考虑的与逻辑相关的警告。结果仍然是正确的。

答案 1 :(得分:3)

通常,"前缀索引"没用。我曾经看过当我认为可以使用前缀索引时忽略前缀索引的情况。

如果您的TEXT字段永远不会超过255个字符,请将其更改为VARCHAR(255)(或更小);然后使用真实的索引,而不是前缀索引。

  

它会给我所有以' a'开头的行。还是会检查整列值?

假设您有INDEX(textcol(1)),则必须扫描以a开头的所有行,以查找包含textcol = 'ab'的行并仅传递这些行。请注意,这是一个性能问题,而不是正确性问题(正如@Michaelsqlbot那样雄辩地阐述)。