2013-04-15 40 views
1

一些性能問題IAM戰鬥在一個非常簡單的表,這似乎通過其主鍵(BIGINT)MySQL不使用主BIGINT指數

獲取數據時很慢我有這個表1.24億項目:

CREATE TABLE `nodes` (
    `id` bigint(20) NOT NULL, 
    `lat` float(13,7) NOT NULL, 
    `lon` float(13,7) NOT NULL, 
    PRIMARY KEY (`id`), 
    KEY `lat_index` (`lat`), 
    KEY `lon_index` (`lon`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 

和一個簡單的查詢這需要一些ID使用IN子句來從節點表中的數據的另一個表,但它需要樣1僅跟小時,從該表中獲取幾行。 EXPLAIN顯示我不使用PRIMARY鍵作爲索引,它只是簡單地掃描整個表。爲什麼? id和另一個表中的id列都來自類型bigint(20)。

mysql> EXPLAIN SELECT lat, lon FROM nodes WHERE id IN (SELECT node_id FROM ways_elements WHERE way_id = '4962890'); 
+----+--------------------+-------------------+------+---------------+--------+---------+-------+-----------+-------------+ 
| id | select_type  | table    | type | possible_keys | key | key_len | ref | rows  | Extra  | 
+----+--------------------+-------------------+------+---------------+--------+---------+-------+-----------+-------------+ 
| 1 | PRIMARY   | nodes    | ALL | NULL   | NULL | NULL | NULL | 124035228 | Using where | 
| 2 | DEPENDENT SUBQUERY | ways_elements  | ref | way_id  | way_id | 8  | const |   2 | Using where | 
+----+--------------------+-------------------+------+---------------+--------+---------+-------+-----------+-------------+ 

查詢SELECT node_id FROM ways_elements WHERE way_id = '4962890'只是返回兩個節點ID,所以整個查詢應該只返回兩行,但它需要更多或更少的1小時。

使用「強制索引(PRIMARY)」沒有幫助,即使這會有所幫助,爲什麼MySQL不會因爲它的主鍵而接受該索引? EXPLAIN甚至沒有提到possible_keys列中的任何內容,但select_type顯示PRIMARY。

我做錯了什麼?

+2

你試過重寫你的子查詢JOIN,看看這是否更快? (我會嘗試兩個方向,左和右加入。) – CBroe

+0

哦,男人,就是這樣。使用LEFT OUTER JOIN可以讓mysql使用主鍵,現在它的速度驚人。謝謝CBroe。 – NovumCoder

回答

1

這是如何執行的?

SELECT lat, lon FROM nodes t1 join ways_elements t2 on (t1.id=t2.node_id) WHERE t2.way_id = '4962890'

我懷疑你的查詢檢查對每個項目的節點每一行「IN」子句。

+0

同樣的答案CBroe給了你,也讚揚你。這是解決方案。謝謝。 – NovumCoder

+0

謝謝。我看到CBroe的評論就像我救了我的答案一樣,我想偉大的思想家都會這麼想。 – Jaydee

1

這就是所謂的相關子查詢。你可以看到this作爲參考或this發佈在Stackoverflow上的熱門問題。一個更好的查詢使用是:

SELECT lat, 
     lon 
FROM nodes n 
JOIN ways_elements w ON n.id = w.node_id 
WHERE way_id = '4962890'