Mysql

在 HDD 上查詢大型數據庫要慢得多

  • February 4, 2020

我有下表:

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 嗎?如果不是,那將是記憶體的因素。

引用自:https://dba.stackexchange.com/questions/258789