2012-04-25 75 views
3

我正在使用MySQL 5.5。我有一個查詢(全文)使用子查詢。爲了提高性能和我正在使用分頁的事實,我使用LIMIT來限制結果的數量。優化計數並選擇查詢

SELECT * 
FROM ( 
    SELECT id, type, type_id, content, MATCH(content) AGAINST('john') as relevance, IFNULL (parent_type, UUID()) as parent_type, IFNULL(parent_id, UUID()) as parent_id 
    FROM search_index 
    WHERE MATCH(content) AGAINST('john*' IN BOOLEAN MODE) GROUP BY parent_type, parent_id) as search 
GROUP BY search.type, search.type_id DESC LIMIT 10; 

除此之外,我需要發回每個搜索查詢的例子(50000)的可能結果的總數。要得到計數,我正在使用:

SELECT COUNT(*) FROM(
    SELECT * 
    FROM ( 
     SELECT id, type, type_id, content, MATCH(content) AGAINST('john') as relevance, IFNULL (parent_type, UUID()) as parent_type, IFNULL(parent_id, UUID()) as parent_id 
     FROM search_index 
     WHERE MATCH(content) AGAINST('john*' IN BOOLEAN MODE) GROUP BY parent_type, parent_id) as search 
    GROUP BY search.type, search.type_id) as count; 

雖然這確實讓我有些不安。下面是計數查詢的解釋:

enter image description here

search_indexcontent一個全文索引。 search_index_no_ft是除了contentid以外的所有列的索引。 id上有一個主鍵。

有沒有更好的方法來做到這一點,也許是一種優化這種方式?或者,有沒有辦法將2個查詢(計數和搜索)合併爲1?

+0

你真的需要確切數量的比賽嗎?谷歌必須有一個原因顯示只有估計... – piotrm 2012-04-25 07:36:37

+0

我需要確切的匹配數量來生成在大多數情況下工作的分頁,例如,當過濾和搜索用戶列表等。如果這是一個普通的網站,因爲數據量如此之大以至於用戶永遠無法完成全部搜索,所以我對估計感到滿意。所以是的,我需要一個完全匹配的用例。 – F21 2012-04-25 08:20:52

+0

無論如何,如果你讓他們這樣做,有些用戶會試圖通過所有這些,濫用基於限制的網站中的最高偏移量是一種常見的DOS攻擊類型。 – piotrm 2012-04-25 08:28:09

回答

0

您是否嘗試過使用SQL_CALC_FOUND_ROWS?它的工作原理是這樣的:

SELECT SQL_CALC_FOUND_ROWS some_fields FROM table WHERE xxx LIMIT 10; 
SELECT FOUND_ROWS(); 

唯一的限制是您必須在第一個查詢後立即執行第二個查詢。
更多在mysql文檔:http://dev.mysql.com/doc/refman/5.0/en/information-functions.html#function_found-rows
不知道它將如何表現與concurnt查詢,所以你將不得不檢查這一點。

+0

對不起,我剛剛意識到我在我的問題中犯了一個致命的錯誤。我需要返回搜索可能行的總數以及由LIMIT設置的行的子集。我想要的效果與搜索引擎相似:'顯示10000個可能結果中的10個'和前10個結果等等(取決於用戶所在的頁面)。 – F21 2012-04-25 07:06:20