1

我使用了这个查询,mysql 给出结果的时间太长了。行数为 160 万。

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

它仍然一样慢。

那我该怎么办?

4

4 回答 4

1

你真的需要tablebusiness在 FROM 子句中包含表三次吗?我已经重写了这个并使用了 JOIN。检查您的 WHERE 条件。TitleLIKE '%%'是什么?试试这个简化的查询 -

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 子句中使用的字段上添加索引也将加快查询速度。

于 2012-05-31T07:46:41.007 回答
1

做什么explain select ...show create table tablebusiness \G说什么?

MySQL 如何使用索引进行范围查询有一些限制,请务必阅读。

根据我对许多用例的经验,在 MySQL 中使用 b-tree 索引比空间索引更有效。我建议将经度和纬度更改为整数(乘以适当的数字以获得“小数”并确保您有一个跨越两列(alter table tablebusiness add index latlon (latitude,longitude))的索引。

于 2012-05-31T07:38:08.493 回答
1

您在经度和经度列上有 BTree 索引吗?

于 2012-05-31T07:27:20.143 回答
1

只有使用索引才能搜索查询的某些部分。所以你必须有一个索引。由于 MySQL 具有(地理)空间数据的扩展,因此您应该查找它并使用 R-tree 索引。这是对两列进行范围限制的最有效类型。

于 2012-05-31T07:24:49.547 回答