簡體   English   中英

MySQL 聚集索引與非聚集索引性能

[英]MySQL Clustered vs Non Clustered Index Performance

我在 MySQL Clustered vs Non Clustered 索引上運行了幾個測試,其中我有一個表100gb_table包含約 6000 萬行:

100gb_table schema:
CREATE TABLE 100gb_table (
    id int PRIMARY KEY NOT NULL AUTO_INCREMENT,
    c1 int,
    c2 text,
    c3 text,
    c4 blob NOT NULL,
    c5 text,
    c6 text,
    ts timestamp NOT NULL default(CURRENT_TIMESTAMP)
);

我正在執行一個只讀取聚集索引的查詢:

SELECT id FROM 100gb_table ORDER BY id;

我看到這個查詢需要大約55 分鍾才能完成,這非常慢。 我通過在主鍵列頂部添加另一個索引來修改表,並運行以下查詢,強制使用非聚集索引:

SELECT id FROM 100gb_table USE INDEX (non_clustered_key) ORDER BY id;

這在<10 分鍾內完成,比使用聚集索引讀取要快得多。 為什么這兩者之間會有如此大的差異? 我的理解是,兩個索引都將索引列的值存儲在樹結構中,除了聚集索引包含葉節點中的表數據,因此我希望兩個查詢具有相似的性能。 BLOB 列可能會扭曲聚集索引結構嗎?

答案在於數據的布局方式。

PRIMARY KEY與數據“聚集”在一起; 也就是說,數據是由PK在B+Tree結構中排序的。 要讀取所有ids ,必須讀取整個 BTree。

任何二級索引也是 B+Tree 結構,但它包含 (1) 索引的列,以及 (2) PK 中的任何其他列。

在您的示例中(有很多 [大概] 龐大的列),數據 BTree 比二級索引大得多(僅在id上)。 任一測試都可能需要從磁盤讀取所有相關塊。

附注......這並不像它可能的那么糟糕。 一行的大小有大約 8KB 的限制。 足夠短的TEXTBLOB列包含在該 8KB 中。 但是當一個笨重時,它會被放在另一個地方,留下一個指向文本/blob的“指針”。 因此,數據 BTree 的主要部分比直接包含所有文本/blob 數據的情況要小。

由於SELECT id FROM tbl是一個大部分不必要的查詢,InnoDB 的設計並不擔心您發現的低效率。

添加ORDER BYWHERE等,並且有許多不同的優化可以發揮作用。 您甚至可能會發現INDEX(c1)會讓您的查詢在不超過 10 分鍾的時間內運行。 (我想我已經為你提供了“為什么”的所有線索。)

另外,如果你已經完成了SELECT * FROM tbl ,它可能需要比 55 分鍾更長的時間。 這是因為有額外的 [隨機] 提取以從“非記錄”存儲中獲取文本/blob。 而且從網絡上挖出的數據要多得多。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM