【发布时间】:2015-06-01 15:34:43
【问题描述】:
我有以下 MySQL 查询:
SELECT
a.*,
( 3959 * acos( cos( radians('47.3909') ) * cos( radians( a.lat ) ) * cos( radians( a.lng ) - radians('-122.2637') ) + sin( radians('47.3909') ) * sin( radians( a.lat ) ) ) ) AS distance
FROM zip_codes AS a
ORDER BY distance ASC
LIMIT 1;
这将为我提供zip_codes 表中最接近我指定坐标的邮政编码。
但是,这运行得很慢! 1秒左右。所有类似的查询也运行大约 1 秒。我想知道是否可以优化我的表结构或查询以缩短查询时间。
这是我的zip_codes 表的架构:
CREATE TABLE `zip_codes` (
`zip` varchar(10) COLLATE utf8_unicode_ci NOT NULL,
`city` varchar(64) CHARACTER SET utf8 DEFAULT NULL,
`state` char(2) CHARACTER SET utf8 DEFAULT NULL,
`type` char(1) CHARACTER SET utf8 DEFAULT NULL,
`timezone` int(11) DEFAULT NULL,
`lat` varchar(255) CHARACTER SET utf8 DEFAULT NULL,
`lng` varchar(255) CHARACTER SET utf8 DEFAULT NULL,
`country` varchar(2) COLLATE utf8_unicode_ci DEFAULT '',
PRIMARY KEY (`zip`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci ROW_FORMAT=COMPACT;
更新我将 lat 和 lng 的字段类型更改为 DECIMAL,现在查询实际上需要更长的时间,令人惊讶!
【问题讨论】:
-
您已更改数据类型,但我怀疑您仍在隐式地将变量转换为字符串。另外,只是好奇...如果您订购
( 3959 * acos( cos( radians('47.3909') ) * cos( radians( a.lat ) ) * cos( radians( a.lng ) - radians('-122.2637') ) + sin( radians('47.3909') ) * sin( radians( a.lat ) ) ) ))会发生什么 -
当我更改 ORDER BY @Strawberry 时的完全相同的性能
-
你能与邮政编码表数据共享一个 sql 转储或 sqlfiddle 吗?我知道我可以自己制作它,我只是想要一个快速测试游乐场来尝试实现我的一个想法。谢谢
-
@Alexey - canary-file-drop.s3.amazonaws.com/zip_codes.sql.zip - 这是一个 SQL 转储。
-
谢谢,将尝试在本地测试一些东西。如果它比您最初的解决方案效果更好,我将作为答案发布
标签: mysql indexing coordinates geospatial