mysql - Mysql索引优化使用范围之间的位置
问题描述
我有一个 mysql 表(1,612,480),其中包含以下行:
id,
origin_zip_start
origin_zip_end
destination_zip_start
destination_zip_end
zone
我添加了索引,origin_zip_start,origin_zip_end,destination_zip_start,destination_zip_end,zone
因为我认为在 where 语句中使用时应该添加索引。
当我尝试使用这个查询时,它返回 500ms;而且我想不出一种聪明的方法来进行扫描。
SELECT
`carrier`,
`zone`,
`service`
FROM
`zone_charts`
WHERE (`origin_zip_start` <= 123
AND `origin_zip_end` >= 123)
and(`destination_zip_start` <= 456
AND `destination_zip_end` >= 456
OR `destination_zip_start` <= 45678
AND `destination_zip_end` >= 45678)
AND `zone` IS NOT NULL
即使它使用了我的索引,它仍然扫描 1.6m。
Describe: my_index 1603448 1.45 Using where
在这种情况下有没有添加索引的好方法?我见过很多添加索引的聪明方法,但我找不到适合我的想法。
数据库表如下所示,并显示前 3 位数字。目标 zips 有时包含 5 位数字,这就是我在查询中使用 OR 语句的原因。
origin_zip_start: OS
origin_zip_end: OE
destination_zip_start: DS
destination_zip_end: DE
OS | OE | DS | DE | zone
123 | 124 | 444 | 446 | 3
125 | 126 | 444 | 446 | 5
127 | 130 | 446 | 446 | 3
解决方案
(目前对于评论来说太大了;我希望将其扩展为答案。)
把想法大声说出来...
正如您所发现的,“范围”是在WHERE
子句中优化的麻烦。
如果每个邮政编码范围都由某人“拥有”(如“城市”)会怎样。那么 12340..12459 可能“属于”堪萨斯州的 Anytown。
现在,您可以非常有效地将 12345 变成“Anytown, Kansas”。潜在的优势是这是一个单点,而不是一个范围。这显示了 IP 地址的等效问题(和解决方案):http: //mysql.rjweb.org/doc.php/ipranges
现在,我对您的问题空间的理解变得模糊。该查询似乎在谈论将一个城市 (123) 与其他两个城市 (456 或 45678) 中的任何一个连接起来。但我很困惑——似乎 45678 包含在 456 中。
另一个困惑...您是否有多个从 123 到 456 的“运营商”?
(给我一些关于你的任务的更多见解;我也许能够更进一步、更有效地传达这个概念。)
推荐阅读
- assembly - Kernel.c 没有执行完整的代码 [操作系统从头开始]
- javascript - 如何在 sequelize(V5) 中使用 IF() 条件
- javascript - 如何将java脚本变量分配给PHP变量
- java - Android中的蓝牙通信无法获取消息
- php - 为什么愿望清单中的数据无法显示
- node.js - 从 SQL Server 中完全删除时区
- websocket - Ballerina:回调时出现多个 websocket 错误
- facebook - Facebook登录颤动应用程序错误与本机登录
- javascript - estimateDocumentCount() 返回一个对象而不是一个数字
- model-checking - 确定两个布尔函数何时等效?