【发布时间】:2015-10-10 04:09:20
【问题描述】:
mysql前缀索引可以像普通索引一样使用吗?
如果有一些TEXT 列并且其上的前缀索引的长度是例如1,查询是:
SELECT * FROM table WHERE textcol = 'ab'
它会给我所有以“a”开头的行还是会检查整个列的值?
总的来说,我很想知道在使用前缀索引时是否有任何注意事项。与性能无关,如果任何查询必须以不同的方式编写或客户端是否必须执行额外的逻辑,则更多。
【问题讨论】:
mysql前缀索引可以像普通索引一样使用吗?
如果有一些TEXT 列并且其上的前缀索引的长度是例如1,查询是:
SELECT * FROM table WHERE textcol = 'ab'
它会给我所有以“a”开头的行还是会检查整个列的值?
总的来说,我很想知道在使用前缀索引时是否有任何注意事项。与性能无关,如果任何查询必须以不同的方式编写或客户端是否必须执行额外的逻辑,则更多。
【问题讨论】:
很多时候,“前缀索引”是无用的。我见过一些情况,当我认为它可以使用它时,它会忽略前缀索引。
如果您的 TEXT 字段永远不会超过 255 个字符,请将其更改为 VARCHAR(255)(或更小);然后使用真正的索引,而不是前缀索引。
它会给我所有以“a”开头的行还是会检查整个列的值?
假设您有INDEX(textcol(1)),那么它必须扫描所有以a 开头的行以找到textcol = 'ab' 的行并仅传递这些行。请注意,这是一个性能问题,而不是正确性问题(正如 @Michaelsqlbot 雄辩地阐明的那样)。
【讨论】:
如果你想一想,即使有 no 索引,MySQL 仍然会给你正确的答案......它不会那么快......所以,是的,你仍然会得到带有前缀索引的正确答案。
性能会降低,因为在将“可能”行与索引匹配后,服务器将转到行数据并根据WHERE 子句进一步过滤结果。两个步骤而不是一个步骤,但应用程序不需要关心任何事情。
需要注意的是,优化器不会将前缀索引用于某些操作,例如排序或分组,因为它没有涵盖足够的列数据用于这些目的。
前缀索引的排序不会超出前缀的长度。如果您的查询使用完整索引来查找行,您通常会发现返回的行是按索引顺序隐式排序的。如果您的应用程序期望这种行为,那么它当然期望它不应该期望的东西,因为返回行的顺序是未定义的,除非您明确地ORDER BY。在任何查询中都不要依赖巧合的行为,因为不仅前缀索引匹配的行不一定是任何特定的顺序......而且实际上任何排序不明确的结果集的顺序都是主题随时更改。
而且,前缀索引不能用作覆盖索引。覆盖索引是指SELECT 中的所有列碰巧一起包含在一个索引中的情况(加上可选的主键,因为它也总是在那里)。优化器将直接从索引中读取数据,而不是使用索引来识别行来查找主表数据。即使索引不能用于查找匹配的行,优化器也会只对覆盖索引进行全扫描,而不是对整个表进行全扫描,从而节省 I/O 和时间。 (顺便说一句,这个功能应该是选择你想要的列的足够理由,而不是懒惰的SELECT *——它可能会打开一些更有效的查询计划)。前缀索引也不能用于此。
但除了性能和优化以及隐式执行您期望(您不应该期望)的查询之外,没有与前缀索引有关的逻辑相关警告。结果仍然是正确的。
【讨论】: