Mysql

不是索引的列是否與索引一起在磁碟上排序?

  • January 7, 2017

在 MySQL、MyISAM 和 InnoDB 中,不是索引的列是否與索引一起在磁碟上排序?

我開始寫的一個錯誤想法:

我認為可能不是,因為它們沒有被索引;如果它們已排序,則意味著它們是索引。

這是不正確的,因為每個索引列都按其自己的內容順序排序,但我問的是每行(或僅某些列)及其相應索引的排序。

為了解釋,我說:這將有助於更快地選擇按索引並排的行範圍。例如,如果我想select * where id >1000 and id<2000(可能是 MySQL 語法有錯誤,我不是很了解),那麼 id 列本身可以快速從磁碟讀取,因為它的 1000 到 2000 的單元格可能在物理磁碟上保持在一起. 但是id 1000到2000對應的其他列內容可能會寫在物理磁碟的不同位置。如果它們也被排序,它們將被更快地讀取。我認為,也許 MySQL 會自動對物理磁碟上的列進行排序,以執行此類操作。

它們是否在其他類型的數據庫(PostgreSQL 等)中排序?

12 月 27 日:我從 2 個答案中看到,在存在聚集索引/主鍵的情況下,簡單行本身並沒有在物理磁碟上排序(我認為它可能/可能是),甚至聚集索引也是未排序,如果它是 b-tree,我已經閱讀了 b-tree 並看到它的節點,據我所知,停留在磁碟上的隨機位置。

在某些情況下,它們可能會被排序。排序索引通常稱為分群。如果是這種情況,那麼整個表都儲存在這樣的索引中(通常在某種 B 樹結構中)。

在另一種情況下,表結構被稱為,行在它們到來時儲存,刪除數據塊中的“空洞”,這些空洞稍後會被新行填充,因此甚至不保留“插入順序”。

MyISAM 使用結構,每一行都由數據文件中的偏移量(*數組索引的排序)標識。*然後每個索引包含每行的索引列,以正確的順序排序並使用偏移數來定位實際行。這意味著通過任何索引訪問該行意味著在索引(B-tree)中定位正確的節點,然後從數據文件中讀取正確的偏移量(可能會隨機查找到磁碟的不同部分) )。

InnoDB 通過主鍵使用集群(或者如果沒有定義,則使用第一個非空唯一鍵,或者添加內部自動遞增列 - 所以行總是以某種方式排序)。在這種情況下,主鍵的訪問是“直接”的,當找到正確的值時,您手頭就有整行,無需進行第二次讀取。另一方面,二級索引不能像 MyISAM 那樣儲存偏移量(因為 B-tree 會動態地重新平衡自身,因此特定行的偏移量可以隨時更改),而是儲存行的主鍵值 - 所以通過輔助鍵訪問意味著 InnoDB 中的兩個 B-tree 搜尋。

MS SQL Server 提供了使主鍵(或另一個索引)成為聚集或非聚集的選項,因此您可以在(沒有聚集的索引)和樹結構(一個索引是聚集的)之間進行選擇。所有其他非聚集索引在堆情況下儲存特殊 (RowID) 值或在 CI 情況下儲存行的聚集鍵值。

PostgreSQL 僅使用表,但允許您根據需要通過某些索引對它們重新排序(您必須觸發它,因此在操作之後對行進行排序,但進一步寫入表可能會再次破壞該順序)。

TokuDB(第 3 方 MySQL/MariaDB 引擎)可以在一個表上使用多個集群鍵 - 它有效地維護了表的多個副本,每個副本以不同的方式排序。它對寫入有懲罰,但 TokuDB 聲稱使用了一些他們稱之為分形索引的東西,這應該會使這種懲罰非常小。

如果您需要為某些查詢使用該功能,您可以通過創建覆蓋索引來“模擬”它- 這樣您的查詢所需的列可以隨時以正確的順序提供,但這再次意味著維護(的部分) 索引中的表。

一般來說,對數據庫的簡短回答是:不,表中行的物理順序通常與該表的某些索引中的不同。

一般來說(我說一般是因為在特殊情況下這是不正確的)表和索引是磁碟上的兩種不同的物理結構。傳統的 RDBM 儲存數據,因此來自一個表(而不是)的值在磁碟上彼此相鄰;行本身不以任何特定順序儲存。另一方面,索引條目是按順序儲存的;一個典型的 b-tree 索引包含索引列的排序值(但不是其他列!)和某種指向表中整行位置的指針,正如我之前所說,它是磁碟上的一個單獨的物理結構。

話雖如此,但也有特殊情況。例如,MySQL 的 InnoDB 將實際數據行儲存在類似索引的結構中。在這種“索引表”中放置行的索引通常是表的主鍵;而這樣的索引稱為聚集索引。但當然,InnoDB 表可能有其他索引,並且這些索引中的行排序(即包含在相應索引中的行列)與表本身的行排序無關。

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