2012-10-30 134 views
3

我正在處理帶有「狀態」列的表,該列通常只包含2個或3個不同的值。有時,當這臺擁有幾百萬行,下面的SQL語句變慢(我假設全表掃描完成):SQLite:使用COUNT和GROUP BY加速SQL語句

SELECT state, count(*) FROM mytable GROUP BY state 

我希望能得到這樣的:

disabled | 500000 
enabled | 2000000 

(基本上我想知道有多少項目「啓用」,有多少項目是「禁用」的 - 實際上這是一個數字,而不是實際應用中的文本)

我想爲我的狀態列添加一個索引是相當無用的,因爲在那裏只能找到極少數不同的值。我還有什麼其他選擇?

還有一個「時間戳」列(帶索引)。眼下

WHERE timestamp BETWEEN x AND y 

我使用一個sqlite3的數據庫,但它看起來像其他數據庫引擎都沒有太大的不同,所以對於其他數據庫引擎的解決方案可能是有趣的:理想的解決方案還應該工作得很好,如果我添加好。

謝謝!

+2

你的執行計劃是什麼樣的? –

+0

SQLite只給了我一行,在「詳細信息」列中說「TABLE mytable」(我猜是全表掃描)。 – Jens

+0

但是,MS SQL告訴我相同的語句(上面沒有where條件和200萬行):SELECT 0%,Compute Scalar 0%,Hash Match(Aggregate)65%,Clustered Index Scan 35% – Jens

回答

1

我會在時間戳,狀態(按此順序)上放置覆蓋索引。其基本原理是:

  • 上的時間戳的條件會比狀態

  • 如果狀態仍然是在指數更具有選擇性(即覆蓋索引)時,發動機只需要產生一個(無需支付隨機I/O訪問表中的主要數據)。

注意:如果時間戳範圍太寬,儘管有索引,它也會變慢。因爲隨機I/O比順序I/O更昂貴,所以索引範圍掃描將比表掃描更昂貴。作爲一個經驗法則,如果您需要掃描超過10%的表格,引擎應該考慮保留表格掃描並忽略索引。我注意到,sqlite足夠聰明,可以支持這種優化。

+0

謝謝。看起來我必須以某種方式存儲預先計算的值(可能是整天或數週的總和),以便查詢時間範圍較寬的查詢。 – Jens