Mysql: 前缀索引 vs 索引

Mysql: Prefix index vs index

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

如果有一些 TEXT 列并且其前缀索引的长度是例如1 并且查询是:

SELECT * FROM table WHERE textcol = 'ab'

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

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

如果你想一想,MySQL仍然会给你正确的答案,即使有没有索引...只是不会一样快......所以,是的,你仍然会得到带有前缀索引的正确答案。

性能会降低,因为在将"possible"行与索引匹配后,服务器将转到行数据并根据WHERE子句进一步过滤结果。两步而不是一步,但应用程序无需关心。

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

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

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

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

很多时候,"prefix index" 是没有用的。当我认为它可以使用它时,我已经看到它忽略前缀索引的情况。

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

Would it just give me all rows starting with 'a' or would it check the whole column value?

假设您有 INDEX(textcol(1)),那么它必须扫描所有以 a 开头的行以找到具有 textcol = 'ab' 的行并仅传送这些行。请注意,这是一个性能问题,而不是正确性问题(正如@Michaelsqlbot 所说的那样)。