2010-10-04 78 views
1

我想建立一個新的表,使現有表中的值不包含在另一個表中(但明顯包含以下檢查)。以下是我的表結構:重寫這個子查詢?

mysql> explain t1; 
+-----------+---------------------+------+-----+---------+-------+ 
| Field  | Type    | Null | Key | Default | Extra | 
+-----------+---------------------+------+-----+---------+-------+ 
| id  | int(11)    | YES |  | NULL |  | 
| point  | bigint(20) unsigned | NO | MUL | 0  |  | 
+-----------+---------------------+------+-----+---------+-------+ 

mysql> explain whitelist; 
+-------------+---------------------+------+-----+---------+----------------+ 
| Field  | Type    | Null | Key | Default | Extra   | 
+-------------+---------------------+------+-----+---------+----------------+ 
| id   | bigint(20) unsigned | NO | PRI | NULL | auto_increment | 
| x   | bigint(20) unsigned | YES |  | NULL |    | 
| y   | bigint(20) unsigned | YES |  | NULL |    | 
| geonetwork | linestring   | NO | MUL | NULL |    | 
+-------------+---------------------+------+-----+---------+----------------+ 

我的查詢看起來是這樣的:

SELECT point 
    FROM t1 
WHERE EXISTS(SELECT source 
       FROM whitelist 
       WHERE MBRContains(geonetwork, GeomFromText(CONCAT('POINT(', t1.point, ' 0)')))); 

解釋:

+----+--------------------+--------------------+-------+-------------------+-----------+---------+------+------+--------------------------+ 
| id | select_type  | table    | type | possible_keys  | key  | key_len | ref | rows | Extra     | 
+----+--------------------+--------------------+-------+-------------------+-----------+---------+------+------+--------------------------+ 
| 1 | PRIMARY   | t1     | index | NULL    | point  | 8  | NULL | 1001 | Using where; Using index | 
| 2 | DEPENDENT SUBQUERY | whitelist   | ALL | _geonetwork  | NULL  | NULL | NULL | 3257 | Using where    | 
+----+--------------------+--------------------+-------+-------------------+-----------+---------+------+------+--------------------------+ 

查詢花費6秒在T1執行了1000條記錄這是我無法接受。如果我沒有要加入的列,我該如何使用Joins重寫此查詢(或者如果存在更快的方法)?我猜在最壞的情況下,即使是存儲過程也是可以接受的。我的目標是最終創建一個包含t1條目的新表。有什麼建議麼?

+0

是否地理網有一個空間索引呢?如果沒有,那麼添加一個應該有所幫助。 – YWE 2010-10-04 21:48:02

+0

@YWE:Yeap。 explain命令中顯示的MUL用於空間索引。 – Legend 2010-10-04 21:49:49

+0

只是好奇,你最終做了什麼來解決你的問題? – Snekse 2011-03-16 15:28:14

回答

0

這似乎是一種情況下,可能有益於去極化t1。添加一個值爲GeomFromText(CONCAT('POINT(', t1.point, ' 0)'))GeomFrmTxt列可以加快您已有的查詢速度。

+0

我的問題是,這種方法需要兩遍:一個將列添加到t1和另一個來過濾它和其額外的數據。我的實際表格包含十億條記錄,因此向它添加更多數據將會使事情變得非常糟糕。我想充分利用這些指標,並一次性完成此操作。 – Legend 2010-10-04 21:56:54

+0

我想我的評論意思是在創建時添加該行,而不是在查詢時。總的來說,您將節省處理時間在您的服務器上,因爲您只需計算一次GeomFromText,而不是每次運行此查詢。也許你存儲我建議的列,並擺脫點列:-)可能不是一個選項,我敢肯定。 – Snekse 2010-10-04 22:03:53

1

除非查詢優化器失敗,否則WHERE EXISTS構造應產生與具有GROUP子句的聯接相同的計劃。看看優化MBRContains(geonetwork, GeomFromText(CONCAT('POINT(', t1.point, ' 0)')))),這可能是您的查詢花費所有時間的地方。我不具備的一項建議,但這裏是你的查詢與JOIN寫着:

 
Select t1.point 
from t1 
join whitelist on MBRContains(whitelist.geonetwork, GeomFromText(CONCAT('POINT(', t1.point, ' 0)')))) 
group by t1.point 
; 

或者得到T1點不在白名單:

 
Select t1.point 
from t1 
left join whitelist on MBRContains(whitelist.geonetwork, GeomFromText(CONCAT('POINT(', t1.point, ' 0)')))) 
where whitelist.id is null 
; 

+0

它給了我相同的執行時間,除了在explain語句的Extra列中,它提到:'爲每個記錄檢查範圍(索引mp:0x2);不存在' – Legend 2010-10-04 22:07:35