在 WHERE 子句已编入索引的情况下,如何加快此 MySQL 查询的速度?
How can I speed up this MySQL Query where the WHERE clauses are already indexed?
我有以下查询,处理时间在 300 毫秒到 450 毫秒之间。
table 大约有 30 万行,大小为 46 MB。
我创建了以下索引:
- Index1 - country 和 countryiso
- Index2 - city 和 cityabbr
- Index3 - city and cityabbr and country and country iso
SELECT latitude, longitude, timezone
FROM geolocate WHERE
(LCASE(country) = 'cambodia' OR LCASE(countryiso) = 'cambodia')
AND
(
(LCASE(city) = 'kaôh préab' OR LCASE(cityabbr) = 'kaôh préab')
);
300 毫秒我觉得时间太多了,但我不确定如何让它更快。
我已尝试创建单独的列索引,但无济于事。
如果有人能提供任何帮助,我将不胜感激。
假设您的 table 中的列使用 utf8
字符集及其默认排序规则 utf8_general_ci
:
您不需要 LCASE()
函数调用,因为 MySQL 已经使用了不区分大小写的比较。例如,将 LCASE(country) = 'cambodia'
更改为 country = 'cambodia'
。
排序规则被嵌入到索引中,因此如果存在索引,这会很有效。
您的 index2 是不必要的,因为它也包含在 index3 中。
具有 OR
操作的查询往往很慢。可以使用一些技巧来加快速度。
我不知道你的索引是否正确。为此,您需要显示您的 EXPLAIN 结果和您的 table 定义。请read this note about asking good SQL questions,并注意查询性能部分。
我会就如何更改您的列定义提供建议,但您没有给我们您的 table 定义。
(O.Jones 解释了如何摆脱 LCASE
;我将在给定查询的上下文中解决 OR
。)
计划 A:让您的应用程序识别名称是全名还是缩写。如果您期望标准的 2 个字母 country_code,例如 KH
,则检查输入的长度并构建适当的查询以避免 OR
。 country_code
应该是 CHAR(2)
CHARACTER SET ascii`。
B 计划:将 OR
变成 UNION
。使用原始查询,您需要 UNION
中的 4 SELECTs
。计划 A 后,您只需 2 个即可逃脱。
计划 C:查找 table city
的所有变体——拼写、缩写、中文等。这个 table 将映射到规范拼写主要用于table。有了这个,你就可以避免 OR
for city
.
方案 D:增加一个 TEXT
列,其中包含 city、cityabbrev、country、countryabbrev。以及可能的变体拼写。使用 FULLTEXT
索引此列。警告:short 'words' 存在问题;您可能应该将最小标记大小设置为 2 以捕获 country_code.
我有以下查询,处理时间在 300 毫秒到 450 毫秒之间。
table 大约有 30 万行,大小为 46 MB。
我创建了以下索引:
- Index1 - country 和 countryiso
- Index2 - city 和 cityabbr
- Index3 - city and cityabbr and country and country iso
SELECT latitude, longitude, timezone
FROM geolocate WHERE
(LCASE(country) = 'cambodia' OR LCASE(countryiso) = 'cambodia')
AND
(
(LCASE(city) = 'kaôh préab' OR LCASE(cityabbr) = 'kaôh préab')
);
300 毫秒我觉得时间太多了,但我不确定如何让它更快。
我已尝试创建单独的列索引,但无济于事。
如果有人能提供任何帮助,我将不胜感激。
假设您的 table 中的列使用 utf8
字符集及其默认排序规则 utf8_general_ci
:
您不需要 LCASE()
函数调用,因为 MySQL 已经使用了不区分大小写的比较。例如,将 LCASE(country) = 'cambodia'
更改为 country = 'cambodia'
。
排序规则被嵌入到索引中,因此如果存在索引,这会很有效。
您的 index2 是不必要的,因为它也包含在 index3 中。
具有 OR
操作的查询往往很慢。可以使用一些技巧来加快速度。
我不知道你的索引是否正确。为此,您需要显示您的 EXPLAIN 结果和您的 table 定义。请read this note about asking good SQL questions,并注意查询性能部分。
我会就如何更改您的列定义提供建议,但您没有给我们您的 table 定义。
(O.Jones 解释了如何摆脱 LCASE
;我将在给定查询的上下文中解决 OR
。)
计划 A:让您的应用程序识别名称是全名还是缩写。如果您期望标准的 2 个字母 country_code,例如 KH
,则检查输入的长度并构建适当的查询以避免 OR
。 country_code
应该是 CHAR(2)
CHARACTER SET ascii`。
B 计划:将 OR
变成 UNION
。使用原始查询,您需要 UNION
中的 4 SELECTs
。计划 A 后,您只需 2 个即可逃脱。
计划 C:查找 table city
的所有变体——拼写、缩写、中文等。这个 table 将映射到规范拼写主要用于table。有了这个,你就可以避免 OR
for city
.
方案 D:增加一个 TEXT
列,其中包含 city、cityabbrev、country、countryabbrev。以及可能的变体拼写。使用 FULLTEXT
索引此列。警告:short 'words' 存在问题;您可能应该将最小标记大小设置为 2 以捕获 country_code.