簡體   English   中英

優化mysql查詢以使用空間索引選擇多邊形中的所有點

[英]Optimizing mysql query to select all points with in polygon using spatial indexes

首先,我承認我的空間功能經驗非常少。 我在MySQL中有一個包含20個字段的表和23549187個包含地理數據的記錄。 其中一個字段是“點”,它是點數據類型並且在其上具有空間索引。 我有一個查詢,選擇多邊形內的所有點,如下所示,

select * from `table_name` where ST_CONTAINS(ST_GEOMFROMTEXT('POLYGON((151.186 -23.497,151.207 -23.505,151.178 -23.496,151.174 -23.49800000000001,151.176 -23.496,151.179 -23.49500000000002,151.186 -23.497))'), `point`)

這很好用,因為多邊形很小。 但是,如果多邊形變得龐大,執行時間變得非常慢,最慢的查詢到現在為止已經運行了15分鍾。 添加指數確實有助於將其降低到15分鍾,否則將花費近一個小時。 我有什么可以做的,以進一步改進。 此查詢將由作為守護程序運行的PHP腳本運行,我擔心這種慢速查詢會導致MySQL服務器崩潰。

我們歡迎所有建議讓它變得更好。 謝謝。

編輯:

show create table;

CREATE TABLE `table_name` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `lat` float(12,6) DEFAULT NULL,
  `long` float(12,6) DEFAULT NULL,
  `point` point NOT NULL,
  PRIMARY KEY (`id`),
  KEY `lat` (`lat`,`long`),
  SPATIAL KEY `sp_index` (`point`)
) ENGINE=MyISAM AUTO_INCREMENT=47222773 DEFAULT CHARSET=utf8mb4

我不應該在這里披露更多的字段,但過濾器贏了

解釋慢查詢的sql輸出:

+----+-------------+------------+------+---------------+------+---------+------+----------+-------------+
| id | select_type | table      | type | possible_keys | key  | key_len | ref  | rows     | Extra       |
+----+-------------+------------+------+---------------+------+---------+------+----------+-------------+
|  1 | SIMPLE      | table_name | ALL  | NULL          | NULL | NULL    | NULL | 23549187 | Using where |
+----+-------------+------------+------+---------------+------+---------+------+----------+-------------+

用較小的多邊形解釋sql輸出以進行查詢,

+----+-------------+------------+-------+---------------+----------+---------+------+------+-------------+
| id | select_type | table      | type  | possible_keys | key      | key_len | ref  | rows | Extra       |
+----+-------------+------------+-------+---------------+----------+---------+------+------+-------------+
|  1 | SIMPLE      | table_name | range | sp_index      | sp_index | 34      | NULL |    1 | Using where |
+----+-------------+------------+-------+---------------+----------+---------+------+------+-------------+

看起來最大的多邊形不使用索引。

MySQL使用R-Trees來索引空間數據。 B-Tree索引一樣 ,這些索引最適合針對總數的一小部分的查詢。 隨着邊界多邊形變大,可能匹配的數量增加,並且在某些時候,優化器決定切換到全表掃描更有效。 這似乎是這里的情景,我看到三個選項:

首先,嘗試在查詢中添加LIMIT 通常,如果優化器在完整表掃描中得出的I / O搜索次數較少,則MySQL會忽略該索引。 但是,至少使用B-Tree索引,MySQL將使該邏輯短路並且在LIMIT存在時始終執行B-Tree潛水。 我假設R-Tree有類似的短路。

其次,與第一個類似,嘗試強制MySQL使用索引 這指示MySQL表掃描比優化器決定的更昂貴。 理解優化器只有啟發式,並且不知道“昂貴”的東西是如何超出其內部統計數據的結論。 我們人類有直覺,有時 - 有時 - 知道更好。

select * force index (`sp_index`) from `table_name` where ST_CONTAINS(ST_GEOMFROMTEXT('POLYGON((151.186 -23.497,151.207 -23.505,151.178 -23.496,151.174 -23.49800000000001,151.176 -23.496,151.179 -23.49500000000002,151.186 -23.497))'), `point`)

最后,如果那些不起作用,那么你需要做的是將邊界多邊形分解成更小的多邊形。 例如,如果您的邊界多邊形是每邊500公里的正方形,則將其分成每邊250平方公里的4個方格,或每邊125平方公里,等等。然后UNION所有這些組合在一起。 索引將用於每個索引,累積結果可能更快。 (注意:這是重要的UNION在一起:MySQL不能在空間查詢應用多個范圍掃描)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM