我有一個包含兩列的表TEST:
- 一個varchar(250)
- B tinyint(1)
該表有大約 400 萬行。A包含 UTF8 字串,B只能是 0 或 1。
select count(1) from TEST非常快(從 MySQL Workbench 開始為 0,000 秒),但select count(1) from TEST where B=1需要大約 15 秒(在相當快的機器上,但在具有更多列的真實表上,對于此問題應該無關緊要)。為B添加索引沒有幫助 - 它仍然進行全表掃描。強制使用索引也沒有幫助。
存盤引擎是 MyISAM,因為選擇比插入/更新多得多,這可能是最好的選擇。
如何加快此查詢的速度?
uj5u.com熱心網友回復:
很遺憾,你提出了一個令人討厭的問題。沒有什么魔法可以避免對您向我們展示的查詢進行全表或全索引掃描。
編輯為什么簡單地計算所有行的速度如此神奇?@BillKarwin 在他的評論中解釋了這一點。您使用 MyISAM 存盤引擎,它在其元資料中維護表的總行數,因此可以SELECT COUNT(*) FROM mytbl立即滿足。添加 WHERE 子句后,它需要掃描所有行。
改善這種情況的建議涉及使用某種匯總表。在其他一些 RDBMS SQL 中,這將被稱為“物化視圖”。例如,您可以創建此表:
CREATE TABLE tablecounts AS
SELECT COUNT(*) num, B
FROM mytbl
GROUP BY B;
ALTER TABLE tablecounts ADD UNIQUE INDEX B (B);
然后每隔一段時間,也許是從重復發生的EVENT,你更新它:
INSERT INTO tablecounts (num, B)
SELECT COUNT(*) num, B
FROM mytbl
GROUP BY B
ON DUPLICATE KEY UPDATE SET num=VALUES(num);
然后您的應用程式可以SELECT num FROM tablecounts WHERE B=1獲取您在問題中提到的計數。
這不是一個完美的解決方案。當然,這個計數會隨著應用程式的其他部分在原始表中插入、更新或洗掉行而變得陳舊,直到您運行該事件。但是你會很快得到一個大概的計數。
編輯如果您確實需要SELECT A FROM tbl WHERE B = 0索引的詳細結果,(B, A)則僅通過掃描相關行來幫助您提高性能。如果您的大多數行都有B = 1索引,那么通過為 MySql 提供一種完全忽略它們的方法,將會有很大幫助。
uj5u.com熱心網友回復:
B 樹索引對于高基數資料(即具有許多可能值的列,其中列中的資料是唯一的或幾乎唯一的)最有效。B 樹索引在如此小的基數列上很糟糕。創建位圖索引。
位圖索引是一種特殊型別的資料庫索引,它使用位圖。此技術用于大型資料庫,當列的基數較低并且這些列在查詢中最常使用時。
在您的情況下,B 列只有兩個值,因此基數低,然后使用位圖索引使用此
CREATE BITMAP INDEX Index_Name ON TEST (B);
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/342393.html
上一篇:鑒于`showvariableslike'%version%';`的輸出,我如何確定我應該使用什么語法?[復制]
