2014-02-23 68 views
2

我的網站上有一個頂級列表頁面,它在特定列中獲取25行的最高值。如果基於一列(例如分數),我沒有問題提取頂級列表,但是當涉及更多列時,我遇到了一些性能問題。有效地獲取25行,最高的兩列總和(MySQL)

在有問題的情況下,我想選擇25行,按降序排列兩列總和。

SELECT username, rank1 + rank2 AS rank FROM users ORDER BY rank DESC LIMIT 25

該查詢工作,但需要大約爲0.25秒完成,而相比之下,查詢在單柱中取約0.0003。以下是解釋查詢的結果:

 
id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra 
1 | SIMPLE  | accounts | ALL | NULL   | NULL | NULL | NULL | 517874 | Using filesort 

rank1和rank2都被編入索引,但顯然這些索引不用於此查詢。有沒有辦法通過編輯查詢或索引來提高性能?

+0

我正在刪除sql-server標記,因爲語法是針對MySQL的。 –

+0

你可以多說一下'rank1'和'rank2'列中值的分佈嗎? –

+0

你有沒有試過在'(username,rank1,rank2)'上添加一個索引? –

回答

2

MySQL並沒有很好地處理這種情況。其他數據庫(例如Oracle,Postgres,SQL Server)提供了某種形式的基於函數的索引,可以直接解決這個問題。要在MySQL中執行此操作,需要在表中添加一個新列,然後添加一個觸發器以使其保持最新狀態。最後是新專欄的索引。也許很多工作。

在某些情況下,您可能會認爲總和排名前XXX位於每個排名的前YYY位置。如果這是真的,那麼像這樣的查詢會提高性能:

select ur1.* 
from (select u.* 
     from users u 
     order by rank1 desc 
     limit 1000 
    ) ur1 join 
    (select u.* 
     from users u 
     order by rank2 desc 
     limit 1000 
    ) ur2 
    on ur1.username = ur2.username 
order by ur1.rank1 + ur1.rank2 desc 
limit 25; 

這由每個排名提取前1000名(或其他值),然後確定普通用戶的兩個列表。 希望有25個這樣的用戶(爲您的應用程序)。至少,這應該比整體查詢執行得更好。你可以先試試這個。如果它返回25行,那麼很好。否則,請進行原始查詢。

+0

創建一個新列並設置觸發器,以提高我所尋找的性能。謝謝! – Lassi