為什麼資料庫列的字元長度為191? - Grouparoo

banq發表於2021-05-19

有時,當您檢視資料庫的架構時,會看到有這樣定義的文字欄位:

email_address varchar(191) NOT NULL

這意味著該列支援最大長度為191個字元的字串,並且不能為null。191是個奇數-它是從哪裡來的?在這篇文章中,我們將瞭解在大多數關聯式資料庫中將191個字元限制為預設值的歷史原因。
 

為什是麼varchar不是text呢?
您可能要問的第一個問題是,為什麼要完全限制可以儲存在資料庫中的字串的長度?所有現代流行的關聯式資料庫支援(幾乎)無限大小的串用text或blob型列,那麼為什麼不放開限制呢?原因是索引。
如果要按列進行搜尋,例如說email_address,您可能想在執行以下操作時為其新增索引以加快處理速度:

select id from users where email = 'foo@example.com';


隨著表變大,搜尋變得越來越慢,因為資料庫必須檢查每一行以找到匹配項。但是,如果新增搜尋索引,則將告訴您的資料庫實質上是用樹“預先計算”流行的搜尋模式,因此下一次搜尋要快得多。本質上,索引花費計算時間(和少量磁碟空間)使對資料庫的寫入速度變慢,從而在以後加快讀取速度。對於大多數應用程式來說,這是一個很大的折衷,因為它們“重讀”和“輕寫”。
那麼,為什麼要使用varchar?如果可以假設索引儲存的資料型別,則可以使索引更好地執行。知道索引中的字串有多長時間是加快速度的最佳方法之一。對於某些資料庫,不允許您將搜尋索引新增到text型別的列中,因為無法完成此最佳化,而在其他資料庫中,索引的效能將不佳。實際上,從歷史上看,資料庫是在建立索引以最佳化搜尋以及將資料儲存在磁碟上的方式方面受到限制的。
 

MySQL的錯
好的,所以索引很好。但是,總的來說,任何大小的索引似乎都可以工作,儘管今天確實如此,但這並不總是可行的。我們看看過去預設的列大小是多少,即255個字元,例如:

email_address varchar(255) NOT NULL

MySQL是2000年代初期最流行的開源資料庫,索引欄位中的字元數上限為255個。關於MySQL為什麼選擇255個字元限制的歷史是模糊的(請參閱下面的連結),但是最受歡迎的理論包括:
  • 256是您可以用8位整數表示的最大數字。MySQL非常關心速度和記憶體使用情況,因此希望以儘可能小的資料型別儲存事物。
  • MySQL本身試圖與甚至更舊的資料庫(sybase / SAP)相容,並且它們的字元數限制為255個。
  • MySQL希望確保其索引檔案可以放在舊檔案系統上的單個頁面塊中。

考慮到256個字元的限制,MySQL開發人員感到很樂於根據255個字元的限制進一步最佳化資料庫的許多部分(稍後將對此進行更多介紹)。由於在那個時期啟動了許多流行的開源應用程式框架(Wordpress,Django和Rails僅舉幾例),所以即使它們可以在多種資料庫型別(如postgres)上執行,它們都遵循MySQL的預設值。這形成了大多數ORM(物件-關係對映-Wikipedia )要使用的通用預設值varchar(255),而與使用的資料庫無關。
 

為什麼不是191而是255?
255比191更好,為什麼限制為191?因為表情符號,utf8mb4字符集允許包括表情符號。在2000年代初期,MySQL很高興在varchar列中支援255個字元並對其進行索引,當時最流行的文字編碼是Latin1或utf8,innodb假定3個位元組足以儲存每個字元,但是,現在utf8mb4需要4個位元組來儲存每個字元。
MySQL資料庫內部innodb:只能有767個位元組的索引-足以儲存255個3位元組字元(767/3 = 255)。這是基於瞭解正在索引的資料大小的索引最佳化的一個極端示例!因此,如果字元佔用更多空間來儲存,那麼您可以索引的字元數必須減少。具體來說,767/4 = 191。
隨著更多軟體支援國際使用者,預設情況下使用varchar(191)替換varchar(255)。對於不需要支援國際使用者的軟體應用程式,一旦使用者開始期望表情符號支援(通常與智慧手機的興起相關聯),則在2010年代初他們也需要升級。
 

總結
utf8mb4字元編碼已成為預設設定,而固定長度索引已成為歷史。但是,在許多應用程式中,我們仍然具有這些191個字元的預設值,以確保相容性。無論如何,當索引知道它們要比較的字串的大小時,它們仍然可以發揮最佳效能,因此出於速度原因,我們仍然希望對列長度​​進行一些限制,並且由於歷史和慣性,191限制仍然存在。

相關文章