日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

mysql 数值 字符 优化,教你如何进行Mysql数据类型优化

發(fā)布時間:2025/3/20 数据库 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 mysql 数值 字符 优化,教你如何进行Mysql数据类型优化 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

1. 版本

1)操作系統(tǒng)版本

cat /proc/version

Linux version 3.10.0-957.5.1.el7.x86_64 (mockbuild@kbuilder.bsys.centos.org) (gcc version 4.8.5 20150623 (Red Hat 4.8.5-36) (GCC) ) #1

2)數(shù)據(jù)庫版本

mysql --version

mysql? Ver 14.14 Distrib 5.7.22, for linux-glibc2.12 (x86_64) using? EditLine wrapper

2. 問題描述

2.1 問題發(fā)現(xiàn)

這是一個朋友跟我咨詢的問題,幫他分析解決這個問題中,我發(fā)現(xiàn)這個問題也正好有效的印證了我們常說的mysql 數(shù)據(jù)類型優(yōu)化原則,既選擇更小的數(shù)據(jù)類型(在滿足業(yè)務(wù)使用的情況下)。在此拿出來跟大家分享一下。他的問題如下:

他在兩張表上進行關(guān)聯(lián)查詢,如果兩張表都是utf8 字符集那么查詢會很快。如果兩張表是utf8mb4字符集那么查詢就比較慢。

下面建兩張測試表,來重現(xiàn)朋友當(dāng)時的現(xiàn)象

1. 創(chuàng)建兩張字符集為 utf8 的表

create table test_join_1(id int,name varchar(250)) default character set utf8;

create table test_join_2(id int,name varchar(250)) default character set utf8;

2. 查看sql 的執(zhí)行計劃

#這里該sql寫的是否有優(yōu)化空間,不在我們本次討論范圍

explain select a.* ,b.id from `test_join_1` a left join(SELECT name, min(id) id from `test_join_2` b? group by name) b? on a.name=b.name;

explain select a.* ,b.id from `test_join_1` a left join(SELECT name, min(id) id from `test_join_2` b? group by name) b? on a.name=b.name;

| id | select_type | table? ? ? | partitions | type | possible_keys | key? ? ? ? ?| key_len | ref? ? ? ? ? ? ? | rows | filtered | Extra? ? ? ? ? ? ? ? ? ? ? ? ? ?|

|? 1 | PRIMARY? ? ?| a? ? ? ? ? | NULL? ? ? ?| ALL? | NULL? ? ? ? ? | NULL? ? ? ? | NULL? ? | NULL? ? ? ? ? ? ?|? ? 1 |? ?100.00 | NULL? ? ? ? ? ? ? ? ? ? ? ? ? ? |

|? 1 | PRIMARY? ? ?| | NULL? ? ? ?| ref? | ? ?| | 753? ? ?| test_chen.a.name |? ? 2 |? ?100.00 | NULL? ? ? ? ? ? ? ? ? ? ? ? ? ? |

|? 2 | DERIVED? ? ?| b? ? ? ? ? | NULL? ? ? ?| ALL? | NULL? ? ? ? ? | NULL? ? ? ? | NULL? ? | NULL? ? ? ? ? ? ?|? ? 1 |? ?100.00 | Using temporary; Using filesort |

3 rows in set, 1 warning (0.00 sec)

3. 轉(zhuǎn)換表的字符集為 utf8mb4

#注意 utf8 字符集轉(zhuǎn)換成 utf8mb4不會有問題,當(dāng)時 utf8mb4 向 utf8 轉(zhuǎn)換不能保證沒有問題

ALTER TABLE test_join_1 CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;

ALTER TABLE test_join_2 CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;

4. 轉(zhuǎn)換字符集后再次查看sql 的執(zhí)行計劃

explain select a.* ,b.id from `test_join_1` a left join?(SELECT name, min(id) id from `test_join_2` b? group by name) b? on a.name=b.name;

| id | select_type | table? ? ? | partitions | type | possible_keys | key? | key_len | ref? | rows | filtered | Extra? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? |

|? 1 | PRIMARY? ? ?| a? ? ? ? ? | NULL? ? ? ?| ALL? | NULL? ? ? ? ? | NULL | NULL? ? | NULL |? ? 1 |? ?100.00 | NULL? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?|

|? 1 | PRIMARY? ? ?| | NULL? ? ? ?| ALL? | NULL? ? ? ? ? | NULL | NULL? ? | NULL |? ? 2 |? ?100.00 | Using where; Using join buffer (Block Nested Loop) |

|? 2 | DERIVED? ? ?| b? ? ? ? ? | NULL? ? ? ?| ALL? | NULL? ? ? ? ? | NULL | NULL? ? | NULL |? ? 1 |? ?100.00 | Using temporary; Using filesort? ? ? ? ? ? ? ? ? ? |

3 rows in set, 1 warning (0.00 sec)

##在使用 utf8 字符集時,mysql 為派生表創(chuàng)建了一個索引(auto_key0),這樣a表和派生表之間使用 index Nested-Loop Join(NLJ) 方式關(guān)聯(lián)。在使用 utf8mb4 字符集時 Mysql 使用 Block Nested-Loop Join(BNL) 方式進行關(guān)聯(lián)。NLJ 比 BNL 訪問方式更高效。

通過分析執(zhí)行計劃,相同數(shù)據(jù)的情況下,第一次執(zhí)行會比第二次執(zhí)行更高效,這也符合朋友生產(chǎn)中產(chǎn)生的現(xiàn)象。但是問題是為什么使用 utf8字符集時,會給派生表創(chuàng)建索引,使用utf8mb4時就不會呢?

其實原因很簡單,代價,mysql 會計算給派生表name列索引的長度(派生表name列長度使用b表中name列長度),b表name列 為 varchar(250),在utf8和utf8mb4 字符集下計算出的索引長度分別為 753(utf8 字符集最多使用3個字節(jié)表示一個字符,同時 name 列允許為 null,并且是可變長度類型,所以key_len=250*3+1+2=753) 和 1003(utf8mb4 字符集最多使用4個字節(jié)表示一個字符,同時name列允許為null,并且是可變長度類型,所以key_len=250*4+1+2=1003)

對于 key_len 超過 1000 的列mysql不會為派生表創(chuàng)建 ,這也告訴我們,不要隨意設(shè)置列的長度,在滿足業(yè)務(wù)的情況下,列的長度是越小越好。

2.2 問題原因

在不同的字符集下,mysql 對同一個列創(chuàng)建創(chuàng)建索引的長度是不一樣的,當(dāng)mysql計算在該列上創(chuàng)建索引的長度超過1000的話,就不會對派生表創(chuàng)建索引。

關(guān)于索引長度具體怎么計算下次會分享。

2.3 問題處理

按照規(guī)范設(shè)計和使用數(shù)據(jù)庫。

MySQL 應(yīng)該使用更小的數(shù)據(jù)類型(在滿足業(yè)務(wù)的情況下),理由如下:

1)更小的數(shù)據(jù)類型可能占用的磁盤空間更小,相同的內(nèi)存空間可以緩存更多的記錄,減少IO操作,減少磁盤空間占用

2)更小的數(shù)據(jù)類型意味著CPU可以更快的進行計算。

3)最主要的是,在數(shù)據(jù)庫執(zhí)行過程中MySQL有時會建立一些臨時表進行連接排序或去重操作,在這些臨時表中列的長度跟源表中列的長度一致,列的長度越大,性能也就越不好。所以列的類型盡可能的小。

總結(jié)

以上是生活随笔為你收集整理的mysql 数值 字符 优化,教你如何进行Mysql数据类型优化的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。