【发布时间】:2018-01-02 00:23:09
【问题描述】:
我不知道这是错误还是功能,或者我做错了什么。我继承了一个有几十万行的 MySQL 数据库。该表包括作为 VARCHAR 的字段“full_name”和作为 INT 的“workpack”。
此表的用途之一是在人们开始填写 HTML 表单时提供自动完成功能,这在上述字段中提供。我注意到,当输入“full_name”时,自动完成出现并更新得非常快,但是当为“workpack”输入整数时,自动完成出现和更新的速度很慢,几乎无法使用。
这两个字段都有索引,查询结构的简化示例如下:
SELECT distinct full_name
FROM xx.xx
WHERE full_name LIKE 'Joe Bl%';
解释表明这是按预期使用索引“full_name”。
对“工作包”的几乎相同的查询:
SELECT distinct workpack
FROM xx.xx
WHERE workpack LIKE '153%';
这里的解释表明它没有使用索引“工作包”,即使我使用了 FORCE INDEX。
因为我能看到的唯一区别是一个是 INT,一个是 VARCHAR,所以我决定通过创建表的本地副本并将“workpack”的数据类型更改为 VARCHAR 来进行实验。有效!也许对某些人来说并不奇怪,但我想知道为什么会发生这种情况。显然,我的“工作包”数据应该存储为 INT,因为它就是这样,但要让我的自动完成功能以合理的方式工作,似乎我需要将其更改为 VARCHAR。我意识到 LIKE 是一个字符串函数,但是鉴于 LIKE 函数仍然适用于 INT,是否有逻辑上的技术原因导致它无法使用索引仅仅因为它是一个 INT?
【问题讨论】:
-
当您对 INT 列应用 LIKE 时,会对 VarChar 进行隐式类型转换(这会阻止在所有 DBMS 中使用索引)。而
LIKE '153%表示您没有数值,而是一串数字(如电话号码)。 -
如果
workpack从未打算用于数学运算,那么即使它看起来像数字,也没有理由不在数据库中将其更改为VARCHAR。如果它用于数学,您可以通过添加VARCHAR类型的重复列来快速交易数据量 -
它没有使用索引有一个完全有效的逻辑和技术原因,你的结论是一个谬误。字符串是数字。每个“字母”分配 1 - 4 个字节,具体取决于使用的编码。这是一个数字,内部。当您索引某些文本时,数字序列 存储在有序数据结构中。当您索引一个整数时,一个数字(一个数字,即
1 - 8字节长)存储在一个有序的数据结构中。所以,你有它 - 你告诉 MySQL 将这个1 - 8字节的数字分解成一个在索引中找不到的数字序列。