MySQL之Schema與數據類型優化(三)

Schema與數據類型優化

BLOB和TEXT類型

BLOB和TEXT都是為存儲很大的數據而設計的字符串數據類型,分別采用二進制和字符方式存儲。
實際上它們分別屬于兩組不同的數據類型家族:字符類型是TINYTEXT,SMALLTEXT,TEXT,MEDIUMTEXT,LONGTEXT;對應的二進制類型是TINYBLOB,SMALLBLOB,BLOB,MEDIUMBLOB,LONGBLOB.BLOB是SMALLBLOB的同義詞,TEXT是SMALLTEXT的同義詞。
與其他類型不同,MySQL把每個BLOB和TEXT值當作一個獨立的對象處理。存儲引擎在存儲時通常會做特殊處理。當BLOB和TEXT值太大時,InnoDB會使用專門的"外部"存儲區域來進行存儲,此時每個值在行內需要1~4個字節存儲一個指針,然后再外部存儲區域存儲實際的值。
BLOB和TEXT家族之間僅有的不同時BLOB類型存儲的是二進制數據,沒有排序規則或字符集,而TEXT類型有字符集和排序規則。
MySQL對BLOB和TEXT列進行排序與其他類型是不同的:它只對每個列的最前max_sort_length字節而不是整個字符串做排序。如果只需要排序前面一小部分字符,則可以減小max_sort_length的配置,或者使用ORDER BY SUBSTRING(column, length).
MySQL不能將BLOB和TEXT列全部長度的字符串進行索引,也不能使用這些索引消除排序

磁盤臨時表和文件排序

因為Memory引擎不支持BLOB和TEXT類型,所以,如果查詢使用了BLOB或TEXT列并且需要使用隱式臨時表,將不得不使用MyISAM磁盤臨時表。即使只有幾行數據也是如此(Percona Server的Memory引擎支持BLOB和TEXT類型,同樣的場景下還是需要使用磁盤臨時表)。這會導致嚴重的性能開銷。即使配置MySQL將臨時表存儲再內存塊設備上(RAM Disk),依然需要許多昂貴的系統調用。最好的解決方案是盡量避免使用BLOB和TEXT類型。如果實在無法避免,有一個技巧是在所有用到BLOB字段的地方都使用SUBSTRING(column, length)將列值轉換為字符串(在ORDER BY 子句中也適用),這樣就可以使用內存臨時表了。但是要確保截取的子字符串足夠短,不會使臨時表的大小超過max_heap_table_size或tmp_table_size,超過以后MySQL會將內存臨時表轉換為MyISAM磁盤臨時表。
最壞情況下的長度分配對于排序的時候也是一樣的,所以這一招對于內存中創建大臨時表和文件排序,以及在磁盤上創建大臨時表和文件排序這兩種情況都很有幫助。

例如,假設有一個1000萬行的表,占用幾個GB的磁盤空間。其中有一個uft8字符集的VARCHAR(1000)的列,每個字符最多使用3個字節,最壞情況下需要3000字節的空間。如果在ORDER BY 中用到這個列,并且查詢掃描整個表,為了排序就需要超過30GB的臨時表。
如果EXPLAIN執行計劃的Extra列包含了"Using temporary",則說明這個查詢使用了隱式臨時表

使用枚舉類型(ENUM)代替字符串類型

有時候可以使用枚舉列代替常用的字符串類型。枚舉列可以把一些不重復的字符串存儲成一個預定義的集合。MySQL在存儲枚舉時非常緊湊,會根據列表值得數量壓縮到一個或者兩個字節中。MySQL會在內部將每個值在列表中得為止保存為整數,并且在表的.frm文件中保存"數字-字符串"映射關系的"查找表",
例如,

mysql> CREATE TABLE enum_test(e ENUM('fish', 'apple', 'dog') NOT NULL);
Query OK, 0 rows affected (0.03 sec)
mysql> INSERT INTO enum_test(e) VALUES('fish'), ('dog'),('apple');
Query OK, 3 rows affected (0.02 sec)
Records: 3  Duplicates: 0  Warnings: 0

這三行數據實際存儲為整數,而不是字符串。可以通過在數字上下問環境檢索看到這個雙重屬性:

mysql> SELECT e+0 FROM enum_test;
+-----+
| e+0 |
+-----+
|   1 |
|   3 |
|   2 |
+-----+
3 rows in set (0.05 sec)

如果使用數字作為ENUM枚舉常量,這種雙重性很容易導致混亂,例如ENUM(‘1’,‘2’,‘3’).建議盡量避免這么做。另外一個讓人吃驚的地方時,枚舉字段是按照內部存儲的整數而不是定義的字符串進行排序的:

mysql> SELECT e FROM enum_test ORDER BY e;
+-------+
| e     |
+-------+
| fish  |
| apple |
| dog   |
+-------+
3 rows in set (0.05 sec)

一種繞過這種限制的方式是按照需要的順序來定義枚舉列。另外也可以在查詢中使用FIELD()函數顯式地指定排序順序,但這會導致MySQL無法利用索引消除排序。


mysql> SELECT e FROM enum_test ORDER BY FIELD(e, 'apple', 'dog','fish');
+-------+
| e     |
+-------+
| apple |
| dog   |
| fish  |
+-------+
3 rows in set (0.07 sec)

如果在定義時就是按照字母的順序,就沒有必要這么做了。枚舉最不好的地方是,字符串列表是固定的,添加或刪除字符串必須使用ALTER TABLE,因此,對于一系列未來可能會改變的字符串,使用枚舉不是一個好主意,除非能接受只在列表末尾添加元素,這樣在MySQL5.1中就可以不用重建整個表來完成修改。
由于MySQL把每個枚舉值保存為整數,并且必須進行查找才能轉換為字符串,所以枚舉列有一些開銷。通常枚舉的列表都比較小,所以開銷還可以控制,但也不能保證一直如此。在特定情況下,把CHAR/VARCHAR列與枚舉列進行關聯可能會比直接關聯(CHAR/VARCHAR)列更慢。
為了說明這個情況,讀一個應用中的一張表進行了基準測試,看看在MySQL中執行上面說的關聯的速度如何。該表有一個很大的主鍵:

CREATE TABLE webservicecalls(
day date NOT NULL,
account smallint NOT NULL,
service varchar(10) NOT NULL,
method varchar(50) NOT NULL,
calls int NOT NULL,
items int NOT NULL,
time float NOT NULL,
cost decimal(9,5) NOT NULL,
updated datetime,
PRIMARY KEY(day,account, service, method)
) ENGINE=InnoDB;

這個表有11萬行數據,只有10MB大小,所以可以完全載入內存。service列包含了5個不同的值,平均長度為4個字符,method列包含了71個值,平均產犢為20個字符。
復制一下這個表,但是把service和method字段換成枚舉類型,表結構如下:


CREATE TABLE webservicecalls_enum(
...omitted...
service ENUM(... VALUES omitted ...) NOT NULL,
method ENUM(... VALUES omitted ...) NOT NULL,
...omitted...
) ENGINE=InnoDB;

然后我們用主鍵列關聯這兩個表,下面是所使用的查詢語句:

mysql> SELECT SQL_NO_CACHE COUNT(*) FROM webservicecalls JOIN webservicecalls USING(day, account,service,method);

用VARCHAR和ENUM分別測試了這個語句,結果如表所示
在這里插入圖片描述

從上面的結果可以看到,當把列都轉換成ENUM以后,關聯變得很快。但是當VARCHAR列和ENUM列進行關聯時則慢很多。在本例中,如果不是必須和VARCHAR列進行關聯,那么轉換這些列為ENUM就是個好主意。這是一個通用的設計時間,在"查找表"時采用整數主鍵而避免采用基于字符串的值進行關聯。然而,轉換列為枚舉型還有另外一個好處。根據SHOW TABLE STATUS命令輸出結果中Data_length列的值,把這兩列轉換為ENUM可以讓表的大小縮小1/3.在某些情況下,即使可能出現ENUM和VARCHAR進行關聯的情況,這也是值得的(這很可能可以節省IO)。同樣,轉換后主鍵也只有原來的一半大小了,因為這是InnoDB表,如果表上有其他索引,減小主鍵大小會使得非主鍵索引也變得更小。
在這里插入圖片描述
(該圖只是查詢Data_length,與上面的例子無關)

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/13483.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/13483.shtml
英文地址,請注明出處:http://en.pswp.cn/web/13483.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Spring Cloud整合Sentinel

1、引入依賴 鏈接: 點擊查看依賴關系 父pom <spring.cloud.version>Hoxton.SR12</spring.cloud.version> <spring.cloud.alibaba.version>2.2.10-RC1</spring.cloud.alibaba.version>Sentinel應用直接引用starter <dependency><groupId&…

【UE5.1】* 動畫重定向 (讓你的角色可以使用小白人全部動畫)

前言 這里以小白人動畫重定向給商城資產“Adventure Character”中的角色為例&#xff0c;闡述如何使用UE5.1進行動畫重定向。 步驟 1. 創建一個IK綁定 這里選擇小白人的骨骼網格體 這里命名為“IKRig_Mannequin” 2. 再新建一個IK綁定&#xff0c;這里使用你要替換給的角色…

MyBatis入門——MyBatis XML配置文件(3)

目錄 一、配置連接字符串和MyBatis 二、寫持久層代碼 1、添加 mapper 接口 2、添加 USerInfoXmlMapper.xml 3、測試類代碼 三、增刪改查操作 1、增&#xff08;Insert&#xff09; 返回自增 id 2、刪&#xff08;Delete&#xff09; 3、改&#xff08;update&#xf…

軟考--試題六--中介者模式(Mediator)

中介者模式(Meditor) 意圖 用一個中介對象來封裝一系列的對象交互。中介者使各對象不需要顯式地相互引用&#xff0c;從而使其耦合松散&#xff0c;而且可以獨立地改變它們之間的交互 結構 適用性 1、一組對象以定義良好但是復雜的方式進行通信&#xff0c;產生的相互依賴關…

民國漫畫雜志《時代漫畫》第17期.PDF

時代漫畫17.PDF: https://url03.ctfile.com/f/1779803-1248612629-85326d?p9586 (訪問密碼: 9586) 《時代漫畫》的雜志在1934年誕生了&#xff0c;截止1937年6月戰爭來臨被迫停刊共發行了39期。 ps:資源來源網絡&#xff01;

力扣HOT100 - 1143. 最長公共子序列

解題思路&#xff1a; 動態規劃 class Solution {public int longestCommonSubsequence(String text1, String text2) {int m text1.length(), n text2.length();int[][] dp new int[m 1][n 1];for (int i 1; i < m; i) {char c1 text1.charAt(i - 1);for (int j 1…

深度學習之基于YoloV5的動物識別系統

歡迎大家點贊、收藏、關注、評論啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代碼。 文章目錄 一項目簡介 二、功能三、系統四. 總結 一項目簡介 一、項目背景與目標 在生態研究、動物保護、以及畜牧業等多個領域&#xff0c;對動物進行準確、高效的識別都具有重…

形態學操作:腐蝕、膨脹、開閉運算、頂帽底帽變換、形態學梯度區別與聯系

一、總述相關概念 二、相關問題 1.形態學操作中的腐蝕和膨脹對圖像有哪些影響&#xff1f; 形態學操作中的腐蝕和膨脹是兩種常見的圖像處理技術&#xff0c;它們通過對圖像進行局部區域的像素值替換來實現對圖像形狀的修改。 腐蝕操作通常用于去除圖像中的噪聲和細小的細節&a…

單鏈表oj

練習 1. 刪除val節點 oj鏈接 這道題最先想出來的方法肯定是在遍歷鏈表的同時刪除等于val的節點&#xff0c;我們用第二中思路:不等于val的節點尾插&#xff0c;讓后返回新節點。代碼如下&#xff1a; struct ListNode* removeElements(struct ListNode* head, int val) {str…

XML基礎知識

1. 常見配置文件類型 properties文件,例如druid連接池就是使用properties文件作為配置文件 XML文件,例如Tomcat就是使用XML文件作為配置文件 YAML文件,例如SpringBoot就是使用YAML作為配置文件 json文件,通常用來做文件傳輸&#xff0c;也可以用來做前端或者移動端的配置文件…

軟考高級-信息系統項目管理師案例題選擇題做題總結

1.不應該只會建立變更和配置管理的規則&#xff0c;應該建立變更控制流程 2.變更的影響不應該只由工程師評估 3.沒有對變更和修改進行記錄 4.變更完成后&#xff0c;客戶沒有對變更進行驗證 5.變更沒有通知相關人員 6.變更沒有和配置管理關聯 7.項目變更管理的工作流程&#xf…

SOLIDWORKS科研版的介紹

SOLIDWORKS科研版的介紹 針對研究項目充分利用軟件功能&#xff0c;無任何限制訪問有關工程和科學的最新技術&#xff0c;并與世界各地的其他用戶進行交流。 SOLIDWORKS科研版可為研究人員提供有關 SOLIDWORKS 設計和科學工程技術的最新知識&#xff0c;并使他們與世界范圍內的…

08.CNN

文章目錄 Observation 1Pooling - Max PoolingFlattenApplication&#xff1a;Playing Go使用驗證集選擇模型食物分類 Observation 1 Pooling - Max Pooling Pooling主要為了降低運算量&#xff0c;現在一般不用了&#xff0c;全convolution Flatten Application&#xff1a;P…

學校上課,是耽誤我學習了。。

>>上一篇&#xff08;文科生在三本院校&#xff0c;讀計算機專業&#xff09; 2015年9月&#xff0c;我入學了。 我期待的大學生活是多姿多彩的&#xff0c;我會參加各種社團&#xff0c;參與各種有意思的活動。 但我是個社恐&#xff0c;有過嘗試&#xff0c;但還是難…

Linux|如何在 awk 中使用流控制語句

引言 當您從 Awk 系列一開始回顧我們迄今為止介紹的所有 Awk 示例時&#xff0c;您會注意到各個示例中的所有命令都是按順序執行的&#xff0c;即一個接一個。但在某些情況下&#xff0c;我們可能希望根據某些條件運行一些文本過濾操作&#xff0c;這就是流程控制語句的方法。 …

鯨尾識別獲獎方案總結

文章目錄 1st solution(classification)2nd place code, end to end whale Identification model3rd place solution with code: ArcFace4th Place Solution: SIFT Siamese5th solution blog post code -Siamese7th place Pure Magic thanks Radek solution: classification9…

QGIS DEM數據快速獲取

背景 Dem 是非常重要的數據&#xff0c;30 m 的精度也是最容易獲取的&#xff0c;目前有很多種方式可以獲取&#xff0c;比如地理空間數據云&#xff0c;今天介紹用 QGIS插件獲取。 這種方式的最大優勢是方便快捷。 插件下載與安裝 插件-管理并安裝插件-搜索下載 OpenTopogr…

linux:信號深入理解

文章目錄 1.信號的概念1.1基本概念1.2信號的處理基本概念1.3信號的發送與保存基本概念 2.信號的產生2.1信號產生的五種方式2.2信號遺留問題(core,temp等) 3.信號的保存3.1 信號阻塞3.2 信號特有類型 sigset_t3.3 信號集操作函數3.4 信號集操作函數的使用 4.信號的處理4.1 信號的…

C# Winform實現五子棋游戲(代完善)

實現了基本的玩法。 BoardController.cs using System;namespace GomokuGame {public class BoardController{private static BoardController instance;private readonly int[,] board;private const int boardSize 15;private BoardController(){board new int[boardSize…

uniapp(h5 app) 中 webview和h5通信

1 uniapph5 和h5頁面 通信 h5 window.parent.postMessage(message, *); uniapph5 onload中 window.addEventListener(message, function (e) { // 監聽 message 事件 //console.log(e.origin) console.log(收到的cocos游戲ID,e.data) …