NULL影響mysql效能是‘最佳化軍規’還是‘中醫理論’?用測試資料說話,順便玩玩golang

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

最近公司規範資料庫方面的一些東西,老程式員告訴我mysql裡不準使用null,說是含null值的列沒法索引,對效能影響很大。我第一次聽說這個,對此將信將疑,之前用null並索引並沒有感覺到不妥,可能是資料量小吧。於是我去google了一頓,但是並沒有找到權威的說法。

V2EX——關於null的索引不生效的傳說是真的麼?

by shiny:
由於資料庫的複雜性,以訛傳訛的空間非常大,快趕上中醫養生了。避免使用 NULL 的理由,在高效能MySQL裡有提到一段。建議大家多讀些書,少看網上的奇技淫巧。特意把書翻出來摘錄了下以供參考:
要盡量避免 NULL
要儘可能地把欄位定義為 NOT NULL。即使應用程式無須儲存 NULL(沒有值),也有許多表包含了可空列(Nullable Column),這僅僅是因為它為預設選項。除非真的要儲存 NULL,否則就把列定義為 NOT NULL。
MySQL難以最佳化引用了可空列的查詢,它會使索引、索引統計和值更加複雜。可空列需要更多的儲存空間,還需要在MySQL內部進行特殊處理。當可空列被索引的時候,每條記錄都需要一個額外的位元組,還可能導致 MyISAM 中固定大小的索引(例如一個整數列上的索引)變成可變大小的索引。
即使要在表中儲存「沒有值」的欄位,還是有可能不使用 NULL 的。考慮使用 0、特殊值或Null 字元串來代替它。
把 NULL 列改為 NOT NULL 帶來的效能提升很小,所以除非確定它引入了問題,否則就不要把它當作優先的最佳化措施。然後,如果計劃對列進行索引,就要盡量避免把它設定為可空。

stackoverflow——NULL in MySQL (Performance & Storage)

by Arian Acosta:
Advantage of using NULLS over Empty Strings or Zeros:
1 NULL requires 1 byte
1 Empty String requires 1 byte (assuming VARCHAR)
1 Zero requires 4 bytes (assuming INT)
You start to see the savings here:
8 NULLs require 1 byte
8 Empty Strings require 8 bytes
8 Zeros require 32 bytes
On the other hand, I suggest using NULLs over empty strings or zeros, because they're more organized, portable, and require less space. To improve performance and save space, focus on using the proper data types, indexes, and queries instead of weird tricks.

中英文使用者們對此都是爭論不休,在群裡問了一下老前輩,前輩表示mysql這個東西很玄乎,還是自己寫效能測是最靠譜,說的好那麼開始寫吧。

測試環境

  • mysql 5.7
  • golang 1.9.2
  • mac os 10.13.1

測試思路

  • 建兩張類似的表,有id,name,number三列,給name建索引,兩張表區別是一個允許null一個not_null
  • 隨機產生若干條資料,包含一些name為空白的資料
  • 將相同的資料插入兩個表中,區別空值是一個用null一個用‘’
  • 測試SELECT * FROM table WHERE NAME = ? 的效能

測試代碼

https://github.com/win5do/pla...

進入檔案所在目錄運行:go test -v -run=none -bench=. -benchmem

測試結果

mock100w條資料的結果,null完全沒影響

儲存空間佔用也是相同的,null占空間 ‘’同樣占空間

寫測試代碼碰到的坑

為什麼要用golang,因為最近在學習golang,通過寫代碼來加深對語言的理解。而且golang內建測試載入器,做效能測試非常方便。

第一個坑,以前沒用過golang串連資料庫,寫create語句的時候一直提示syntax error,仔細檢查了好幾遍,沒有錯誤啊。後來翻了翻文檔發現串連是加上multiStatements=true參數才能使用多行sql。

第二個坑就是insert語句拼接的太長會導致write pipe broken,mock50000行時沒問題,但100000行就報錯了,解決辦法就是分塊插入,10000行插一下。

第三個坑,就是query之後是要close的

結論

當前穩定版本mysql5.7之中,null對索引沒有影響(比較懶,5.5沒測試,不想去安裝卸載mysql,有空補上)。不要一棒子把null打死,該用就用,null的語義化很好,配合orm使用基本無痛。比如時間列,不用null用個0000-00-00不要太蛋痛。

那句老話:

過早的最佳化是萬惡之源

僅憑中醫理論最佳化更是無可救藥

更重要的,用golang寫代碼真的很cool

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.