Mysql
在 HDD 上查詢大型數據庫要慢得多
我有下表:
CREATE TABLE `Geo1` ( `id` int(8) UNSIGNED NOT NULL, `nameRef` int(8) DEFAULT NULL, `placeRef` mediumint(7) UNSIGNED DEFAULT NULL, `category` enum(...) COLLATE utf8_bin DEFAULT NULL, `parentRef` mediumint(7) DEFAULT NULL, `incidence` int(9) UNSIGNED NOT NULL, `percent` decimal(11,9) UNSIGNED DEFAULT NULL, `ratio` int(11) NOT NULL, `rank` mediumint(7) UNSIGNED DEFAULT NULL, `year` smallint(4) NOT NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin; ALTER TABLE `Geo1` ADD PRIMARY KEY (`id`), ADD KEY `placeRef_rank` (`placeRef`,`rank`), ADD KEY `nameRef_parentRef` (`nameRef`,`parentRef`), ADD KEY `nameRef_placeRef` (`nameRef`,`placeRef`), ADD KEY `nameRef_category_year` (`nameRef`,`category`,`year`) USING BTREE; MODIFY `id` int(8) UNSIGNED NOT NULL AUTO_INCREMENT;
該表總共為 55GB,索引為 36GB。
在我的本地伺服器(使用 SSD)上,它可以在 0.001 秒內執行以下查詢:
SELECT SQL_NO_CACHE placeRef, incidence FROM Geo1 WHERE nameRef = 1 AND category = "country";
但是在遠端伺服器(使用 HDD)上大約需要 0.1-0.6 秒。該伺服器有 32GB 記憶體。這是mysql.cnf。
兩台伺服器上的 EXPLAIN 結果相同。
關於為什麼這麼慢的任何想法?
有兩個問題
問題 1:MyISAM
MyISAM 不記憶體數據(儲存在 中
.MYD
),這意味著每次都必須為磁碟讀取數據。可以記憶體索引(從 讀取一次.MYI
),但不能記憶體數據。請參閱我在 InnoDB 和 MyISAM 之間的主要區別是什麼中的舊文章?在 MyISAM 子標題下
問題 #2:HDD 與 SSD
HDD 必須使用主軸在磁碟上移動其讀/寫磁頭
SSD 是一種隨機讀/寫設備。它比 HDD 更快地將塊歸零到磁碟。
經驗法則:硬碟上的磁碟命中大約需要 10 毫秒(100 次命中/秒)。SSD 訪問速度可能快 10 倍。
HDD 上的“0.1-0.6”——可能需要獲取 10 到 60 個塊。這可能只有一個用於索引,然後是幾個用於數據。也許結果集中至少有 60 行?
你說慢版本是“遠端”的。這可能會增加一點時間。
0.001 秒通常表示結果集是從查詢記憶體中獲取的。但是你有 SSD 和 SQL_NO_CACHE,所以排除了。結論是所有必要的塊都在記憶體中(.MYI 的 key_buffer 或 .MYD 的 OS)
SELECT SQL_NO_CACHE placeRef, incidence FROM Geo1 WHERE nameRef = 1 AND category = "country";
“覆蓋索引”可能會顯著加快查詢速度:
INDEX(category, nameRef, -- in either order placeRef, incidence) -- in either order
然後查詢將在 key_buffer 中執行,因為所需的一切都在
INDEX
.您確實應該切換到 InnoDB,儘管我認為它不會對此查詢產生任何影響。
兩台伺服器都有 32GB 的 RAM 嗎?如果不是,那將是記憶體的因素。