2017-09-14 81 views
2

我有一個查詢。如下當大數據受到影響時,索引不起作用

SELECT SUM(principalBalance) as pos, COUNT(id) as TotalCases, 
     SUM(amountPaid) as paid, COUNT(amountPaid) as paidCount, 
     SUM(amountPdc) as Pdc, SUM(amountPtp), COUNT(amountPtp) 
    FROM caseDetails USE INDEX (updatedAt_caseDetails) 
    WHERE updatedAt BETWEEN '2016/06/01 00:00:00' AND '2016/06/30 23:59:00' 

它有效地使用索引。截圖結果屏幕截圖:Result of explain 日期範圍'2016/06/01 00:00:00'和'2016/07/26 23:59:00'中有154500條記錄。

但是,當我作爲,

SELECT SUM(principalBalance) as pos, COUNT(id) as TotalCases, SUM(amountPaid) as paid, COUNT(amountPaid) as paidCount, SUM(amountPdc) as Pdc, SUM(amountPtp), COUNT(amountPtp) FROM caseDetails USE INDEX (updatedAt_caseDetails) WHERE updatedAt BETWEEN '2016/06/01 00:00:00' AND '2016/07/30 23:59:00'

現在,這是不使用索引提高數據的範圍。結果解釋屏幕截圖:Result of explain 在日期範圍'2016/06/01 00:00:00'和'2016/07/30 23:59:00'

增加日期範圍查詢不再使用索引,所以它變得太慢了。即使在我被迫使用索引之後。我無法弄清楚爲什麼會發生這種情況,因爲查詢和索引都沒有變化。你能幫我知道爲什麼會發生這種情況嗎?

+0

嘗試使用'force index'而不是'use index'。但一般來說,假設你的數字是正確的,總結20倍的行數當然會更慢。那麼「太慢」的速度有多慢(與其他情況相比)?你在該表中總共有多少行?它可能實際上是一個全表掃描通過索引超過300萬行查找(除非它是一個覆蓋索引,包括您在該查詢中使用的所有列,例如'principalBalance',因此不需要讀取之後的桌子)。 – Solarflare

+0

感謝@Solarflare的輸入。我試過這個,查詢使用索引,但它的處理速度仍然很慢。 –

+2

是的,正如我所說的,如果你有20倍的行數(300萬而不是150k),它應該會變慢。如果它需要的時間少於第一個查詢的20倍,那麼選擇不同的索引是MySQL的一個好主意,並且強制索引可能比以前更慢。你可以嘗試一個完整的覆蓋索引(索引'(update_at,principalBalance,amountPaid,...,amountPtp)'。這個查詢應該更快,但是與所有索引一樣,它會減慢更新/插入,並且會需要空間 – Solarflare

回答

1

更短的時間(很可能)

使用的索引,即使磁盤讀取可能不如將減少(見下文)。大多數磁盤驅動器支持批量讀取也就是說,您可以從以下頁面請求某個塊/頁面以及從n的數據。對於幾乎所有旋轉磁盤,磁帶和其他所有以順序方式訪問數據比隨機訪問更有效的硬盤驅動器(例如......更高效)來說,這一點尤其快速。

本質上,您通過順序讀取與隨機訪問獲得時間優勢。

較少的磁盤讀取(不太可能)

使用的指標是有效的,當你真正獲得速度/效率。當您顯着減少磁盤讀取次數並且需要更少的時間時,索引是好的。當讀取索引並讀取使用索引確定的結果行時,讀取整個表時讀取的磁盤讀數幾乎相同,但使用索引可能不明智。

如果您的數據足夠分散(就搜索條件而言),這很可能會發生,因此您很可能必須閱讀(幾乎)所有頁面/塊。

想法修復

如果你只訪問表以這種方式(即,日期是最重要的搜索條件),則可能非常值得訂購磁盤上的數據的時間。我相信,MySQL的可以提供這樣的功能...(優化表出現做一些這樣)

這將減少使用索引的查詢時間(和索引更可能被使用)

替代

看到Rick James後(主要有:店面聚集,而不是重複計算它們)

+0

謝謝@Jakumi。我會嘗試收集更多關於我的服務器配置的信息。 –

2

不要使用USE INDEXFORCE INDEX。當大多數表被訪問時,這會減慢查詢速度。特別是,如果索引似乎指向超過大約20%的行,則優化器將決定正確地進行表掃描。使用索引涉及在索引和數據之間來回跳動,而執行表掃描順序地順序讀取數據(儘管不得不跳過許多行)。

還有另一種解決方案real問題。我假設您正在構建彙總大型數據倉庫表中數據的「報告」?

而不是總是從原始數據('事實'表)開始,建立和維護一個「彙總表」。對於你的數據,它可能每天有1行。每天晚上,你會爲當天的各種事情計算SUMsCOUNTs。然後,「報告」將對總和進行總和並計算總和以獲得較大日期範圍的期望統計。

更多討論:http://mysql.rjweb.org/doc.php/summarytables

你的「報告」將運行超過10倍的速度,你甚至不會被誘惑FORCE INDEX。畢竟,60行應該比3089464快很多。

相關問題