2011-02-11 46 views
6

我有一個很大的數據集(約190萬行),我正在從中選擇3D點。我最常使用的陳述類似於:在具有大型3D點數據集的SELECT查詢中提高性能

SELECT * FROM points 
WHERE x > 100 AND x < 200 
AND y > 100 AND y < 200 
AND z > 100 AND z < 200 
AND otherParameter > 10 

我在x,y和z以及其他參數上有記號。我也嘗試在x,y,z中添加多部分索引,但這並沒有幫助。

有關如何使這個SELECT查詢更快的任何意見?

+1

您使用範圍查詢。索引是無用的。有時候,如果可以離散值並使用in運算符,就可以實現它。就像:'where x in(100,101,... 200)`這是一篇很好的文章來解釋這種差異 - http://explainextended.com/2009/10/07/in-list-vs-range-condition- mysql/ – 2011-02-11 21:39:35

+0

看看nate c的鏈接,我的「解決方案」是不正確的。 – 2011-02-11 21:51:40

回答

6

B-Tree索引對於這樣的查詢沒有多大幫助。

你需要什麼作爲R-Tree索引和它的最小邊界平行六面體查詢。

不幸的是,MySQL不支持R-Tree索引超過3d分,只有2d。但是,您可以在創建索引時,說:XY在一起,這將是更有選擇性,任何對X獨自01​​的B-Tree指標:

ALTER TABLE points ADD xy POINT; 

UPDATE points 
SET  xy = Point(x, y); 

ALTER TABLE points MODIFY xy POINT NOT NULL; 


CREATE SPATIAL INDEX sx_points_xy ON points (xy); 

SELECT * 
FROM points 
WHERE MBRContains(LineString(Point(100, 100), Point(200, 200), xy) 
     AND z BETWEEN 100 and 200 
     AND otherParameter > 10; 

這是唯一可能的,如果你的表是MyISAM

+0

我需要探索R-Tree。有趣的是,我想出了一個潛在的解決方案,就是添加一個八叉樹字段,將每一行分配給一個節點,然後預處理要選擇的八進制數。這確實有助於加快速度,但是當選擇更大的卷時,由於選擇了大量的樹節點,我遇到了同樣的問題。 – clexmond 2011-02-13 22:25:49

-1

我沒有MySQL的測試,但我很好奇它INTERSECT是多麼有效:

 select points.* 
    from points 
    join 
    ( 
    select id from points where x > 100 AND x < 200 
    intersect 
    select id from points where y > 100 AND y < 200 
    intersect 
    select id from points where z > 100 AND z < 200 
    ) as keyset 
    on points.id = keyset.id 

不一定,建議這一點 - 但它的一些嘗試,特別是如果你有X單獨的索引,y和z。

編輯:因爲mySQl不支持INTERSECT上面的查詢可以使用內聯視圖的JOINS重寫。每個視圖都將包含一個鍵集,每個視圖都會擁有放置在x,y和z上的單獨索引的優勢。性能取決於返回的鍵的數量以及相交/連接算法。

我首先測試了交叉方法(在SQLite中),以查看是否有方法在使用R-Tree模塊的情況下提高空間查詢的性能。 INTERSECT實際上比在其中一個空間值上使用單個非複合索引慢,然後掃描基表的子集以獲取其他空間值。但結果可能因數據庫的大小而異。在表達到龐大的大小和磁盤I/O作爲性能因素變得更加重要之後,將離散鍵集(其中每一個已經從索引實例化)交叉可能更有效,而不是掃描基本表子頻繁到索引的初始讀取。