繁体   English   中英

Mysql如何处理将无字符串值与索引的varchar列进行比较?

[英]How Mysql treats comparing a no string value to a indexed varchar column?

最近我在以下用例中发现了一个性能问题之前我有一个带有INT索引列“MyCode”的表“MyTable”之后需要更改将“MyCode”列转换为VARCHAR的表结​​构(保留了列上的索引)

 ALTER TABLE MyTable CHANGE MyCode MyCode VARCHAR(250) DEFAULT NULL

然后经历了意外的延迟,正在执行的查询如下:

 SELECT * FROM MyTable where MyCode = 1234

这个查询完全忽略了MyCode VARCHAR索引,印象是它是全扫描表

将查询转换为

 SELECT * FROM MyTable where MyCode = "1234"

性能回归到VARCHAR索引的最佳利用

所以问题是......如何解释它......以及MySQL如何处理索引。 或者可能需要更改某些数据库设置以避免这种情况?

int_col  = 1234      -- no problem; same type
char_col = "1234"    -- no problem; same type
int_col  = "1234"    -- string is converted to number, then no problem
char_col = 1234      -- converting all the strings to numbers -- tedious

在第四种情况下,索引是无用的,因此优化器会查找其他一些方法来执行查询。 这很可能导致“全表扫描”。

主要的例外是“覆盖索引”,它只是稍微快一点 - 涉及“全索引扫描”。

我接受了Rick James的回答,因为他明白了。

但是我想在进行一些测试后添加更多信息。

问题中的情况是:当过滤列为varchar类型且提供的filter by值不是字符串时,MySQL实际上如何比较两个值。 如果是这种情况,您将失去利用应用于VARCHAR列的索引的机会,在您的查询中性能会大幅下降,而应该是立即和简单的。

解释是,在与VARCHAR具有不同类型的给定值前面的MySQL将执行全表扫描,并且对于每个记录的字段将执行CAST(varcharcol as providedvaluetype)并将结果与​​提供的值进行比较。

例如

有一个名为“code”的VARCHAR列并进行过滤

   SELECT * FROM table WHERE code=1234

将完全扫描每条记录,就像这样做

    SELECT * FROM table WHERE CAST(code as UNSIGNED)=1234

请注意,如果您将对照0进行测试

  SELECT * FROM table WHERE CAST(code as UNSIGNED)=0

你将收到所有记录,其中包含一个字符串,其CAST到UNSIGNED将不具有mysql CAST函数的无符号含义。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM