我使用了这个查询,mysql花了太长时间才给出结果。行数为1.6百万。
SELECT DISTINCT TB.ID, Latitude, Longitude,
111151.29341326*SQRT(pow(-6-`Latitude`,2)
+pow(106-`Longitude`,2)*cos(-6*0.017453292519943)
*cos(`Latitude`*0.017453292519943)) as Distance
FROM `tablebusiness` AS TB, `tablecity` AS TC, `businessestag` AS BC,
`businessesdistricts` AS BD, `tabledistrict` AS TD,
(SELECT ID,
(SELECT Title
FROM `tablebusiness` As TBuild
WHERE TBuild.ID = TBB.Building) As BuildingTitle
FROM `tablebusiness` As TBB) AS TBuilding
WHERE TB.City = TC.City AND BC.BusinessID = TB.ID AND BD.BusinessID = TB.ID
AND TD.ID = BD.District AND TBuilding.ID = TB.ID
AND (`Title` LIKE '%%' OR `Street` LIKE '%%' OR TB.City LIKE '%%'
OR Country LIKE '%%' OR Tag LIKE '%%' OR TD.District LIKE '%%'
OR TBuilding.BuildingTitle LIKE '%%')
AND (-6.0917668133836 < `Latitude` AND `Latitude` < -5.9082331866164
AND 105.90823318662 < `Longitude` AND `Longitude` < 106.09176681338)
ORDER BY Distance LIMIT 0, 100
即使行数是160万的查询部分,也就是
AND (-6.0917668133836 < `Latitude` AND `Latitude` < -5.9082331866164 AND 105.90823318662 < `Longitude` AND `Longitude` < 106.09176681338)
极大地限制了行数。似乎mysql不会通过搜索
来优化查询AND (-6.0917668133836 < `Latitude` AND `Latitude` < -5.9082331866164 AND 105.90823318662 < `Longitude` AND `Longitude` < 106.09176681338) first.
我通过移动前面的纬度经度方面来改变查询
SELECT DISTINCT TB.ID, Latitude, Longitude,
111151.29341326*SQRT(pow(-6-`Latitude`,2)
+pow(106-`Longitude`,2)*cos(-6*0.017453292519943)
*cos(`Latitude`*0.017453292519943)) as Distance
FROM `tablebusiness` AS TB, `tablecity` AS TC, `businessestag` AS BC,
`businessesdistricts` AS BD, `tabledistrict` AS TD,
(SELECT ID,
(SELECT Title
FROM `tablebusiness` As TBuild
WHERE TBuild.ID = TBB.Building) As BuildingTitle
FROM `tablebusiness` As TBB) AS TBuilding
WHERE (-6.0917668133836 < `Latitude` AND `Latitude` < -5.9082331866164
AND 105.90823318662 < `Longitude` AND `Longitude` < 106.09176681338)
AND TB.City = TC.City AND BC.BusinessID = TB.ID AND BD.BusinessID = TB.ID
AND TD.ID = BD.District AND TBuilding.ID = TB.ID
AND (`Title` LIKE '%%' OR `Street` LIKE '%%' OR TB.City LIKE '%%'
OR Country LIKE '%%' OR Tag LIKE '%%' OR TD.District LIKE '%%'
OR TBuilding.BuildingTitle LIKE '%%')
ORDER BY Distance LIMIT 0 ,100
它仍然很慢。
那我该怎么办?
答案 0 :(得分:1)
只能通过索引搜索查询的某些部分。所以你必须有一个索引。由于MySQL具有(地理)空间数据的扩展,因此您应该查找它并使用R树索引。对于两列,这是最有效的范围限制。
答案 1 :(得分:1)
您是否在朗讯和经度栏上有BTree索引?
答案 2 :(得分:1)
explain select ...
和show create table tablebusiness \G
说什么?
MySQL如何使用index for range queries有一些限制,请务必仔细阅读。
根据我对许多用例的经验,在MySQL中使用b-tree索引比空间索引更有效。我建议将经度和纬度改为整数(乘以适当的数字得到“小数”,并确保你有一个跨越两列(alter table tablebusiness add index latlon (latitude,longitude)
)的索引。
答案 3 :(得分:1)
您真的需要在FROM子句中包含tablebusiness
表三次吗?我重写了这个并使用了JOIN。检查您的WHERE条件。什么是Title
LIKE&#39; %%&#39;?试试这个简化的查询 -
SELECT
TB.ID,
Latitude,
Longitude,
111151.29341326 * SQRT(POW(-6 - `Latitude`, 2) + POW(106 - `Longitude`, 2) * COS(-6 * 0.017453292519943) * COS(`Latitude` * 0.017453292519943)) AS Distance
FROM
`tablebusiness` AS TB
JOIN `tablecity` AS TC
ON TB.City = TC.City
JOIN `businessestag` AS BC
ON BC.BusinessID = TB.ID
JOIN `businessesdistricts` AS BD
ON BD.BusinessID = TB.ID
JOIN `tabledistrict` AS TD
ON TD.ID = BD.District
LEFT JOIN `tablebusiness` TBuilding
ON TBuilding.ID = TB.ID
WHERE
(`Title` LIKE '%%' OR `Street` LIKE '%%' OR TB.City LIKE '%%' OR Country LIKE '%%'
OR Tag LIKE '%%' OR TD.District LIKE '%%' OR TBuilding.BuildingTitle LIKE '%%')
AND (-6.0917668133836 < `Latitude` AND `Latitude` < -5.9082331866164
AND 105.90823318662 < `Longitude` AND `Longitude` < 106.09176681338)
ORDER BY
Distance
LIMIT
0, 100
在JOIN和WHERE子句中使用的字段上添加索引也会加快查询速度。