2012-06-14 52 views
-1

我的SQL查詢出現問題,它運行得非常快,除非它不返回任何結果。MySQL - 查詢速度很慢沒有結果(null)

我有4個表:世界(2項),球員(約2000項),world_chunk(約16000項)和world_block(約1萬件)

SELECT bid,playername FROM worlds 
JOIN world_chunks ON worlds.id = world_chunks.mainid 
JOIN world_blocks ON world_chunks.cid = world_blocks.cid 
JOIN players ON world_blocks.player = players.pid 
WHERE worldname='world' AND x='-684' AND y='63' AND z='-2234' AND cx ='-43' AND cz='-140' 

X,Y,Z舉行在world_blocks和cx中,cz被保存在world_chunks和worldname世界中 所有索引都被設置,並且對於所有內容都是非常快的,只是空的結果。

無論如何我可以加快空結果嗎?

非常感謝你們的幫助。

編輯: 這裏是分貝結構: http://pastebin.com/rxQQ5mzp

及其MySQL的InnoDB的

EXPLAIN on Emtpy Query: 
1 SIMPLE worlds ALL PRIMARY,idx_mainid NULL NULL NULL 2  Using where 
1 SIMPLE world_blocks ALL NULL NULL NULL NULL 766845 Using where; Using join buffer 
1 SIMPLE world_chunks eq_ref PRIMARY,idx_cid PRIMARY 4 WatchBlock.world_blocks.cid 1 Using where 
1 SIMPLE players eq_ref PRIMARY,idx_pid PRIMARY 4 WatchBlock.world_blocks.player 1 

EXPLAIN on Found Query: 
1 SIMPLE worlds ALL PRIMARY,idx_mainid NULL NULL NULL 2 Using where 
1 SIMPLE world_blocks ALL NULL NULL NULL NULL 766845 Using where; Using join buffer 
1 SIMPLE world_chunks eq_ref PRIMARY,idx_cid PRIMARY 4 WatchBlock.world_blocks.cid 1 Using where 
1 SIMPLE players eq_ref PRIMARY,idx_pid PRIMARY 4 WatchBlock.world_blocks.player 1 

結果可以是空的爲x,y,z和CX,CZ不匹配(因此,如果一個這些不是在db中,玩家的結果應該是空的)

+0

「All Indexes are set」*全部* ?!你的意思是你在每一列上都有一個列索引?或者你的意思是你嘗試了所有可能的多列索引,包括所有列列的排列?我懷疑你是這麼做的。你能說明你有什麼指數。 –

+0

請發表正面結果和負面結果的'EXPLAIN'。 – philwinkle

+0

我已經設置了ID,mainid,cid,pid的索引 – user1455025

回答

0

Philwinkle是正確的,它不是特別適合發佈SQL查詢性能問題而不發佈適當的EXPLAIN。您還應該公佈四個表格和相關索引的DDL。你說「所有索引都設置好了」,但是在你的跟蹤評論中,你建議你唯一的索引是在主鍵上,這對查詢來說是不夠的。

對於性能問題,記錄您正在使用的數據庫以及使用的表類型也很有用:您的標記表明這是mysql,這意味着myisam vs innodb是您未能提供的重要信息。最後,你聲稱'空'的結果是緩慢的,但是你不能解釋爲什麼空結果是空的,是空的,因爲其中一個連接是空的,或者是因爲其中一個座標不匹配(如果是, world_block或world_chunk座標)。

如果您提供了EXPLAIN數據和基本的DDL,我不會寫這個,因爲現在問題很可能已經被回答;就目前來看,直到你這樣做,這個問題才能得到合理的回答。我可以提供的最好的方法是,您可能需要添加至少一個覆蓋部分或全部(x,y,z)和(cx,cy)座標的索引;但這只是一個受過教育的猜測。

編輯:

感謝您的解釋,這有助於。正如你毫無疑問已經注意到的那樣,world_blocks的全表掃描是最可能的罪魁禍首。考慮到數據庫的小尺寸,您添加的索引(cid,x,y,z)可能幫助最大。其他幾點:

如果這是一個攝取+讀取數據庫,那麼MyISAM是一個合理的選擇,但是如果您打算執行聯機更新或刪除操作,您最好堅持使用InnoDB。 InnoDB的真正優勢在於併發性/可伸縮性的改進,而不僅僅是參照完整性(儘管您不應低估這一點的重要性)。

如果x,y和z在此查詢中始終保持不變,則應考慮將它們移動到索引的前端。事實上,如果你使用的是InnoDB,這個EXPLAIN建議索引應該在(x,y,z)上,因爲包含cid只會浪費緩衝區緩存。如果你堅持使用MyISAM,你絕對應該考慮在連接引用的字段上使用覆蓋索引:(x,y,z,cid,players),因爲這將阻止全行讀取直到最終的投影。

這引出了我的最終觀點:只要遇到不明原因的性能怪癖,請立即運行EXPLAIN;在不明原因的性能怪癖消失之後,始終運行EXPLAIN並確保其有意義; MyISAM和InnoDB的索引行爲幾乎總是不同的,對其中一個的優化並不總是優化。

+0

我將信息添加到了問題文章中。我很抱歉不知道要發佈什麼。謝謝您的幫助! – user1455025

+0

非常感謝您的詳細信息。現在對我來說更有意義。因爲我事實上有並行刪除和插入,我會確保切換到innodb並使用您的解釋來改善我的查詢! – user1455025