我不知道这是一个错误或功能,还是我做错了什么。我继承了一个有几十万行的MySQL数据库。此表格包含字段" full_name'这是一个VARCHAR,' workpack'这是一个INT。
此表的一个用途是在人们开始填写HTML表单时提供自动完成功能,这在上述字段中提供。我注意到在输入' full_name'自动填充功能会出现并快速更新,但在键入' workpack'自动完成显示和更新很慢,几乎无法使用。
这两个字段都被编入索引,查询结构的简化示例如下:
SELECT distinct full_name
FROM xx.xx
WHERE full_name LIKE 'Joe Bl%';
EXPLAIN建议使用索引' full_name'如预期的那样。
' workpack'几乎完全相同的查询:
SELECT distinct workpack
FROM xx.xx
WHERE workpack LIKE '153%';
这里的EXPLAIN显示它没有使用索引' workpack',即使我使用FORCE INDEX。
因为我能看到的唯一区别是一个是INT而另一个是VARCHAR,我决定通过创建表的本地副本并更改' workpack'的数据类型来进行实验。到VARCHAR。有效!对某些人来说也许并不令人惊讶,但我想知道为什么会这样。显然我的工作包'数据应该存储为INT,因为它是什么,但是为了使我的自动完成功能以合理的方式工作,我似乎需要将其更改为VARCHAR。我意识到LIKE是一个字符串函数,但由于LIKE函数仍然适用于INT,它是否因为它是INT而无法使用索引的逻辑上的技术原因?
答案 0 :(得分:2)
索引在这里不合适,因为您将其转换为字符串。如果您使用其值或字符串表示形式对数字列表进行排序,结果将会有所不同。以示例125和1234为例。按值排序时,您会得到:
按字符串表示法排序时,你会得到:
所以索引在你的情况下没用,因为它是在值的顺序(因为你的字段是一个int),而你的搜索需要字符串顺序(因为你使用like
来找到一些字符串前缀) 。 (请记住,索引实际上只是一个排序列表)
答案 1 :(得分:1)
索引本质上是一种排序数据结构,它从列的值映射到包含它的行。因此,它只能在您的查询使用实际值时使用,而不是对其进行某些转换(例如将Warning messages:
1: running command 'C:\Program Files\mingw-w64\x86_64-5.3.0-posix-seh-rt_v4-rev0\mingw64\bin /c PATH' had status 127
2: In shell("PATH") : 'PATH' execution failed with error code 127
转换为int
)。
针对此类问题的一个简洁解决方案(自MySQL 5.7.6起可用)是添加自动生成的列,仅用于索引并在此类查询中使用它。它可能会浪费一些空间(因为您拥有相同数据的两个副本 - 原始数据和计算列),但如果您的应用程序大量使用此查询,则可能值得:
varchar