2009-08-02 147 views
3

我有一個2GB的MySQL表,500k行,我在沒有負載的系統上運行以下查詢。如何優化這個MySQL慢(非常慢)的查詢?

select * from mytable 
where name in ('n1', 'n2', 'n3', 'n4', ... bunch more...) 
order by salary 

它需要一個文件夾,並在50到70秒之間完成。

當按工資排序並在應用程序中進行排序時,總運行時間(包括排序)將減少到大約25-30秒。但這還是太多了。

任何想法如何加快這一點?

謝謝。

+0

請參閱:http://stackoverflow.com/questions/1204402/how-do-i-ask-for-help-optimizing-fixing-queries-in-mysql – hobodave 2009-08-04 03:58:09

回答

5

將名稱列表放入臨時表中,然後在兩個表上進行內部連接。這種方式比梳理每一行的整個列表要快得多。這是僞代碼:

create temporary table names 
    (name varchar(255)); 

insert into names values ('n1'),('n2'),...,('nn'); 

select 
    a.* 
from 
    mytable a 
    inner join names b on 
     a.name = b.name 

另外請注意,name應該有一個索引。這讓事情變得更快很多。感謝托馬斯做這個筆記。

+3

確保原始表的名稱上有索引充分利用連接。 – 2009-08-02 23:25:03

+0

謝謝,這有點快;對於相同的查詢大約25s,但25s仍然不是真正的改進... – CharlesS 2009-08-02 23:37:21

0
create index xyz on mytable(name(6)); 

「IN」查詢是幾乎送花兒給人低效的,因爲它們是概念性地處理這樣的:

select * from mytable where name = n1 
or name = n2 
or name = n3 
... 

我上面給出可以意味着查詢優化的索引通過索引來訪問行而不是表掃描。

1

一些想法:

  • 你必須選擇*,您可以只選擇一個子集脫身?
  • 如果你能逃脫選擇一個子集,你可以添加一個覆蓋指數,已經由工資排序
  • 如果一切具有相同的模式,你可以不喜歡(「N%」)
1

嘗試使用子查詢選擇想要的行,然後對該子查詢的結果進行排序。 See this question

而且你的name的索引mytable對吧?

1

根據數據分佈和您的WHERE子句匹配的行量,你可能想嘗試(工資,名)索引甚至(姓名,工資)儘管後者很可能將不對於這類查詢非常有用。

您可能還想增加sort_buffer_size設置。單獨測試一切,並比較EXPLAIN的輸出。