2012-02-20 47 views
1

表中有超過200萬條記錄。如何在不編制更多字段的情況下提高計數性能?

我想統計表中有多少錯誤(帶勾選)以及有多少錯誤已被檢查。

我做兩個查詢:

SELECT count(*) as CountError FROM table WHERE checked = 1 AND error != '' 

-

SELECT count(*) as Checked FROM table WHERE checked = 1 

的表現實在是太慢了,它需要大約5分鐘即可得出結果。如何改善?

我已經有UPDATE性能的status字段的索引。

如果我在checked字段索引 - 那麼更新性能將受到影響,我不想這樣做。

更新發生比SELECT更多。

表中Innob

+3

購買更多硬件。不,真的 - 你不能無所事事,所以如果你不願意做出權衡,你需要改變問題的限制。使用'memcache'或更快的機器,或升級數據庫軟件... – Borealid 2012-02-20 19:51:55

+1

這是一個非常基本的查詢。沒有索引'checked'或'error',你就無能爲力。 @Borealid好吧,只需要購買更多的硬件... – 2012-02-20 19:53:01

+0

如果添加索引節省的資源大於添加索引的資源成本,請添加索引。一般而言,您會發現添加索引比獲得成本更有利。除非您可以量化沒有全面儲蓄,否則我通常會在添加所需內容方面犯錯,而不是過度「擔心」對更新的影響。 – MatBailie 2012-02-20 20:07:56

回答

3

你可以嘗試,如果在同一個查詢使這兩個方面是速度快:

select 
    count(*) as CountError, 
    sum(case when error != '' then 1 else 0 end) as Checked 
from table 
where checked = 1 

然而,這種區別可能不會過多談論。如果你真的想要有所不同,那麼你需要添加一個索引。考慮影響真正意味着什麼,並通過實際測試來了解影響可能會發生什麼。如果更新速度降低10%,並且選擇速度提高100000%,那麼它可能還是值得的。

+0

據我所知,第二個聚合可能更簡單在MySQL中:'SUM(error!='')AS Checked'(在這種情況下,布爾值被隱式轉換爲整數:'false' - >'0','true' - >'1')。 – 2012-02-20 20:34:55

0

這裏你的問題很簡單,就是你的檢測場是1或0,這意味着MySQL需要做一個表掃描,即使你有一個關鍵,因爲它是無法有效地確定在何處在0和1之間分割,特別是在大量的行上。

我會提供的主要建議是你不想要的,這是索引檢查,然後SELECT SUM(checked) AS Checked FROM table WHERE checked=1將能夠使用該索引而不打表。

最終,雖然這不是一個簡單的查詢。你可能希望看一些歸檔計數的方法。如果你有一個日期或時間戳,那麼你可以每天設置一個任務,可以存儲前一天的計數(*)。這反過來會留下更少的行來動態解析。

沒有關於此表的確切目的的進一步信息,您不會允許該列上的索引等的原因很難提出任何比上述+投擲硬件更有用的信息。

+0

是的,如果索引不夠有選擇性,索引就沒用了。 – 2012-02-20 22:26:45

+0

他們仍然可以使用有限,但只能從需要有限列的情況下使用索引。然而,對於大多數用途而言,與具有更大範圍的索引(即日期範圍 – 2012-02-20 22:36:33

+0

)相比,它們的改進非常小,對覆蓋索引的索引掃描比表掃描更有效 – 2012-02-20 23:37:03

相關問題