2017-04-04 39 views
2

有沒有辦法優化以下查詢?MySQL高效測試如果計數w /大於某個值

SELECT count(*)>1000 FROM table_with_lot_of_rows WHERE condition_on_index; 

使用此查詢,MySQL首先執行count(*),然後進行比較。只有少數行滿足條件時,這是很快的,但如果有很多行滿足條件,則可以永久使用。有沒有辦法在發現1000個物品時立即停止計數,而不是完成所有結果?

特別是,我對帶有全文條件的MyISAM表感興趣,但對InnoDB和/或基本WHERE子句的任何回答都會有所幫助。

回答

4
SELECT 1 
    FROM table_with_lot_of_rows 
    WHERE condition_on_index 
    LIMIT 1000, 1; 

以這種方式工作:

  1. 使用索引(這大概是快於使用數據)
  2. 跳過1000行,收集沒什麼。 (這比其他答案要好。)
  3. 如果你到目前爲止,取1行,只包含文字1(在SELECT)。

現在你有一個空結果集(< = 1000行)或一行1(至少1001行)。

然後,根據您的應用程序語言,很容易區分這兩種情況。

另注:如果這是要在一個更大的查詢子查詢,然後做

EXISTS (SELECT 1 
    FROM table_with_lot_of_rows 
    WHERE condition_on_index 
    LIMIT 1000, 1) 

它返回TRUE/FALSE(其是具有1或同義0)。

面對它,掃描1001行,甚至索引,將花費一些時間。我認爲我的表述是最快的。

其他要檢查的事項:這是InnoDB嗎? EXPLAIN是否說「使用索引」?多少內存? innodb_buffer_pool_size的設置是什麼?

請注意,InnoDB現在擁有FULLTEXT,所以沒有理由堅持使用MyISAM。

如果您使用的是MyISAM並且WHEREMATCH...,那麼我說的大部分內容可能不適用。 FULLTEXT可能在給予引擎的其餘部分之前獲取所有結果,以便與ORDER BYLIMIT進行這些遊戲。

請向我們展示實際查詢,其EXPLAINSHOW CREATE TABLE。而真正的目標是什麼?查看查詢是否會傳遞「太多」結果?

可能的改進(取決於上下文)

由於我的初始SELECT返回標量1NULL,它可以以任何布爾上下文中使用諸如WHERE1TRUE,NULL將被視爲FALSE。因此EXISTS可能是多餘的。

此外,1/NULL因此可以變成1/0。注:額外的parens是必需的。

IFNULL((SELECT ... LIMIT 1000,1), 0) 
+0

偉大的解決方案,謝謝!對於這個問題,詳細說明我的具體設置可能是無關緊要的,這是對基本'count(*)> 1000'的改進,並且與索引無關。 – M1L0U

+0

'FULLTEXT','SPATIAL','PRIMARY'和其他指標有四種不同的工作方式。 –

+0

我提供了賞金後,我想出了一個修改後的版本,得到我所需的「0」或「1」,而不是「沒有或1」,結果沒有重複閾值(違反DRY),但它仍然基於子查詢(這感覺很難看)。我會留下賞金,看看有人可以做到這一點,沒有風格點的子查詢,但除此之外,賞金是你的鼓舞我。我的修改版本只是將它包裝到COUNT結果的查詢中:'SELECT COUNT(*)FROM(SELECT 1 FROM table_with_lot_of_rows where condition_on_index LIMIT 1000,1);' – ShadowRanger

1

您可以使用子查詢與LIMIT優化查詢:

SELECT count(*)>1000 FROM (
    SELECT 0 table_with_lot_of_rows 
    WHERE condition_on_index 
    LIMIT 1001 
) as truncated_count; 

在這種情況下,MySQL只要足夠的行滿足條件停止。

+0

是的,這應該工作 – MohanaPriyan