2011-04-08 109 views
7

我一直在研究和閱讀有關SQL數據類型幾天(我知道......我知道,這不是很長),我很難掌握的一件事是如何選擇最好的數據鍵入可擴展性,效率和訪問簡易性。爲MySQL選擇數據類型?

我認爲如何選擇基本的數據類型(即int vs varchar)非常簡單,但是如何選擇blob和文本類型之類的東西。

MySQL的手冊頁很棒,但它們並不是我們電腦愛好者所鍾愛的......高效。

我認爲如果我們可以編譯MySQL數據類型列表,每種類型的一般優點/缺點以及何時選擇該數據類型都有意義,那將是非常棒的。

+1

http://www.google.com/search?q=performance+of+mysql+data+types(任何事情在第一頁) – Ben 2011-04-08 00:42:29

+0

我喜歡這個問題,希望有一個深思熟慮的答案,這可以真正幫助我的服務器上的速度(如果我選擇了錯誤的類型)。同時,這篇文章與此有關(和選擇錯誤的數據類型有關的問題)http://m.pinboard.in/blog/173/ – Ben 2011-04-08 01:05:41

+0

@當然是一個鏈接到谷歌,你不認爲閱讀我的問題,我花了一些時間搜索和閱讀什麼是最好的。問題在於沒有以有效的方式彙編這些信息,並且很好地描述了何時使用它們。如果你閱讀5或6篇文章,你會得到大量的信息,但我們可以很容易地在wiki風格列表中匹配。它可以編輯和使用比篩選谷歌結果更​​好。搜索最好的文章是桃花,但它仍然不完整。 :/我想這裏的答案可能會好得多。 – austinbv 2011-04-10 00:35:56

回答

11

MySQL字符串類型有兩種變體:一種不帶字符集標籤,另一種帶有字符集標籤。

一個固定長度的字符串,在末尾用空格填充,是CHAR(n)。沒有字符集標籤的匹配類型是BINARY(n)。在CHAR(255) CHARSET utf8中存儲字符串「hello」需要765個字節(字符串填充的空格爲全長,存儲爲utf8,最壞情況空間使用3個字節/字符分配3 * 255個字節)。

帶有一個或兩個長度字節且沒有填充的可變長度字符串是VARCHAR((n)。沒有字符集標籤的匹配類型是VARBINARY(n)。將字符串「hello」存儲在VARCHAR(255) CHARSET utf8中6個字節(1個長度字節加上用於實際的文本5個字節)。存放字符串ク在同類型將採取(每個字符使用三個字節來表示它們1個長度字節加上3個字符)10個字節リス。

mysql> select hex('クリス'), length(hex('クリス'))/2 as bytes; 
+--------------------+--------+ 
| hex('クリス')  | bytes | 
+--------------------+--------+ 
| E382AFE383AAE382B9 | 9.0000 | 
+--------------------+--------+ 
1 row in set (0.02 sec) 

長度爲1,2,3或4個字符的可變長度字符串是TINYTEXT,TEXT,MEDIUMTEXT和LARGETEXT。沒有字符集標籤的匹配類型是TINYBLOB,BLOB,MEDIUMBLOB和LARGEBLOB。

TEXT/BLOB-like類型與VARCHAR/VARBINARY-like類型在存儲數據的方式和位置上有所不同,請參閱http://www.mysqlperformanceblog.com/2010/02/09/blob-storage-in-innodb/以獲取有關TEXT/BLOB-like類型如何存儲在InnoDB中的詳細信息,具體取決於版本和ROW_FORMAT設置。出於性能方面的原因,您需要最新版本的InnoDB和「Barracuda」格式表。

除非您在服務器端構建複雜且內存緊張的解決方法,否則MySQL無法處理大於max_allowed_pa​​cket(默認值:1M)大小的任何數據。這進一步限制了TEXT/BLOB-like類型可以做什麼,並且通常使LARGETEXT/LARGEBLOB類型在默認配置中無用。

對於沒有字符集標籤(BINARY,VARBINARY和%BLOB%)的類型,MySQL將接受收到的數據並將其寫入磁盤。對於具有字符集標籤的類型,MySQL會查看您宣佈的客戶端字符集爲SET NAMES以及列定義的字符集標籤。然後它將從連接字符集轉換爲列字符集並寫入轉換後的數據。您可以使用HEX()函數來檢查它,例如SELECT HEX(str) FROM t WHERE id = ...

檢索時,該連接宣佈字符集與SET NAMES可以從它已經在寫入時不同。 MySQL將再次檢查列字符集標籤與爲此連接宣佈的字符集,並在必要時將轉換爲連接字符集。

該轉換相比,採取I/O招致這樣的數據反正performancewise它並不重要選擇哪種類型的磁盤時兩種方式都可以忽略不計的性能損失。規則是:如果使用文本數據,則選擇帶有字符集標籤的類型;如果不使用,則選擇不帶類型的類型。


經常問到一個相關的問題:我應該選擇CHAR還是VARCHAR(分別是BINARY還是VARBINARY)?

對於InnoDB,答案總是:之所以選擇可變長度的數據類型。 InnoDB中的固定長度數據類型沒有性能優勢,但如果您選擇固定長度的數據類型,然後沒有使用全部空間,則會有巨大的損失。另外,固定長度的SQL字符串類型有很多奇怪的規則,關於填充和修剪,最後使用空格,您可能無法學習。對於MySQL而言,情況可能不同,但幾乎從不是。


另一個相關的問題:要不要我(分別爲VARBINARY或BLOB)選擇VARCHAR或TEXT我的琴絃?

的答案是使用最新的InnoDB,梭子魚格式表格的版本,然後TEXT/BLOB。詳細解釋原因在於http://www.mysqlperformanceblog.com/2011/04/07/innodb-row-size-limitation/。那其結果是:無論使用哪種VARCHAR或預酷魚格式TEXT/BLOB運行溢滿了InnoDB的行大小限制,如果你有太多的單個行的風險。


最後:我應該在數據庫中存儲文件/圖像/其他大型blob或文本數據?

該答案是:通常不會。與從文件系統提供文件相比,從數據庫提供文件(http://mysqldump.azundris.com/archives/36-Serving-Images-From-A-Database.html)是一項昂貴的操作。如果可能的話,你會想這樣做。有一種方法,http://www.blobstreaming.org/,但這是先進的技術,要求您完全控制您的執行環境,這在託管環境中從未如此。


要捨棄它:在MEMORY引擎表中沒有可變長度的數據類型。所以,如果你看到「使用臨時」在EXPLAIN輸出,這意味着

  • VARCHAR轉換爲CHAR在臨時表
  • VARBINARY轉換成二進制

如果臨時表通過這個過程變得比tmp_table_size或者max_heap_table_size大,它正在被轉換成MyISAM格式並且到磁盤。

示例:您正在定義一個Ruby Active Record類User,其中包含標記爲:string的十個字段。在表中,每個結果都是VARCHAR(255) CHARSET utf8

在您的代碼庫中的其他地方,正在使用Users的方式涉及計劃using temporary。您正在負載下的磁盤操作中立即死亡,因爲Users表的每一行現在在MEMORY中至少使用了7650個字節,其中大多數是用作填充的空格。這強制將臨時錶轉換爲MyISAM並寫入磁盤。

  • 任何%TEXT%或%BLOB%類型不能在內存中表示,因此臨時表進行到磁盤,即使它本來足夠小,以根據上述的限制被保持在存儲器中的MyISAM。

這意味着任何帶有TEXT或BLOB類型的查詢以及帶有「使用臨時」的計劃都需要重寫,以避免臨時表碰到磁盤。

1

關於BLOB和TEXT(因爲這是你的文章中唯一的具體問題):BLOB用於二進制數據,而TEXT用於文本數據。

使用適合您需求的最具體類型的列通常非常簡單,並且如果它們中沒有一個適合您的使用,則回退到泛型類型。

1

對於MySQL,有一個稱爲分析的過程,它將評估啓發式數據的思想,即通知數據類型的最佳選擇,併爲枚舉提供一個或多個值。

快速動態CONCAT腳本生成的SQL運行

select CONCAT(' SELECT ', COLUMN_NAME, ' FROM ', TABLE_NAME, ' procedure analyse() ;') 
FROM INFORMATION_SCHEMA.COLUMNS 
WHERE table_schema ="yourDbName" 
AND DATA_TYPE ="varchar" 
AND CHARACTER_MAXIMUM_LENGTH > 190 
AND COLUMN_KEY not in (' ') ; 

** SQL以上不評估的PK - 假設他們不是文本字段

的程序是有益的面色改變時基於數據使用的數據類型或通過移動或存儲較小的數據包來獲得更高的效率。

Percona博客有一個很好的適用於Drupal的程序分析工作示例。 https://www.percona.com/blog/2009/03/23/procedure-analyse/

一些研究是針對壓縮它關係到更長utf8mb4指標 http://techblog.constantcontact.com/devops/space-the-final-frontier-a-story-of-mysql-compression/