MySql深度優(yōu)化淺析

MySQL注意知識點

INT(N)表示什么?

N是顯示寬度,不表示存儲數(shù)字的長度限制物赶。使用zerofill表示長度小于N時速种,使用0填充高位玻佩,直到長度為N,長度大于N時,按照實際顯示。

自動增長注意點

  1. 自動增長需要設置在主鍵上

  2. 主鍵插入為null或者0時肌割,會自動增長

  3. 主鍵插入負數(shù)時,會按照實際值插入

字符類型

char(n)和varchar(n) 其中n表示的是字符長度帐要。

其它例如text(n)把敞,longtext(n) n表示的是字節(jié)

數(shù)據(jù)庫排列規(guī)則Collation

設置為utf8_general_ci時,會忽略字符的大小寫榨惠。

而使用utf8mb4_bin時奋早,_bin結尾的,不會忽略大小寫

時間類型

日期類型 占用空間 表示范圍
DATETIME 8 1000-01-01 00:00:00 ~ 9999-12-31 23:59:59
DATE 3 1000-01-01 ~ 9999-12-31
TIMESTAMP 4 1970-01-01 00:00:00UTC ~ 2038-01-19 03:14:07UTC
YEAR 1 YEAR(2):1970-2070, YEAR(4):1901-2155
TIME 3 -838:59:59 ~ 838:59:59

DATETIME 沒有時區(qū)的概念赠橙,而TIMESTAMP有時區(qū)的概念

顯示MySQL的最大連接數(shù):

show VARIABLES like '%max_connections%'

MySql緩存默認關閉耽装,開啟后要命中要求2次SQL要完全一樣,包括SQL語句期揪,連接的數(shù)據(jù)庫剂邮,協(xié)議版本,字符集等横侦。

默認關閉緩存:

show variables like '%query_cache_type%'

在 mysql 中 database 和 schema 是等價的

MySQL存儲引擎

Innodb

MySQL5.5以后默認的存儲引擎,完全支持事務和ACID特性绰姻,支持行級鎖枉侧。

MyISAM

MySQL5.5之前默認的存儲引擎,有myd(數(shù)據(jù))和myi(索引)組成

支持表壓縮狂芋,但是表壓縮后榨馁,就不能再插入數(shù)據(jù)了。適用于非事務類型應用帜矾,只讀應用翼虫,空間類應用屑柔。基本上大多數(shù)場景都不適合了珍剑。

Innodb與MyISAM區(qū)別

CSV

  • 以 csv 格式進行數(shù)據(jù)存儲

  • 所有列都不能為 null 的

  • 不支持索引(不適合大表掸宛,不適合在線處理)

  • 可以對數(shù)據(jù)文件直接編輯(保存文本文件內容)

Archive

以 zlib 對表數(shù)據(jù)進行壓縮,磁盤 I/O 更少,數(shù)據(jù)存儲在 ARZ 為后綴的文件中招拙。

只支持 insert 和 select 操作唧瘾,只允許在自增 ID 列上加索引

Memory

  • 文件系統(tǒng)存儲特點,也稱 HEAP 存儲引擎别凤,所以數(shù)據(jù)保存在內存中

  • 支持 HASH 索引和 BTree 索引

  • 所有字段都是固定長度 varchar(10) = char(10)

  • 不支持 Blog 和 Text 等大字段

  • Memory 存儲引擎使用表級鎖

  • 最大大小由 max_heap_table_size 參數(shù)決定

使用場景

  • hash 索引用于查找或者是映射表(郵編和地區(qū)的對應表)

  • 用于保存數(shù)據(jù)分析中產(chǎn)生的中間表

  • 用于緩存周期性聚合數(shù)據(jù)的結果表

Ferderated

  • 提供了訪問遠程 MySQL 服務器上表的方法

  • 本地不存儲數(shù)據(jù)饰序,數(shù)據(jù)全部放到遠程服務器上

  • 本地需要保存表結構和遠程服務器的連接信息

使用場景

偶爾的統(tǒng)計分析及手工查詢(某些游戲行業(yè))

MySQL中的鎖

  1. 表級鎖,適合以查詢?yōu)橹鞴婺模挥猩倭堪此饕龡l件更新數(shù)據(jù)的應用求豫。會把整個表鎖住

  2. 行級鎖,適合按照索引條件并發(fā)更新少量不同數(shù)據(jù)诉稍,同時又有并發(fā)查詢的應用蝠嘉。

  3. 頁面鎖(gap鎖,間隙鎖)

表鎖

  1. 表共享讀鎖均唉。(讀鎖)

  2. 表獨占寫鎖是晨。(寫鎖)

讀鎖

語法:

lock table 表名 read # 加鎖 UNLOCK TABLES # 解除鎖

多個session可共享讀,當前session寫操作會報錯舔箭,其它session寫操作會阻塞罩缴。當前session查詢時,不能設置表別名层扶,否則報錯箫章。

寫鎖

lock table 表名 write # 加鎖 UNLOCK TABLES # 解除鎖

同一個session中,可以進行增刪改操作镜会,其它session的增刪改操作會阻塞檬寂。所有的讀操作都會被阻塞。

行鎖

讀鎖(共享鎖)

BEGIN SELECT * FROM 表名 WHERE 條件 LOCK IN SHARE MODE

COMMIT

一個session開啟一個事務戳表,設置一個行級讀鎖桶至,另外一個session就不能對已經(jīng)上鎖的數(shù)據(jù)進行寫操作。比如設置條件為id <=13,那么對id為小于等于13的數(shù)據(jù)匾旭,都不能進行寫操作镣屹,會阻塞。同個session可以進行操作价涝。

寫鎖(排它鎖)

同一個session中可以進行讀寫操作女蜈,另外一個session就不能對已經(jīng)上鎖的數(shù)據(jù)進行寫操作。比如設置條件為id <=13,那么對id為小于等于13的數(shù)據(jù),都不能進行寫操作伪窖,會阻塞逸寓。

注意點

  1. 兩個事務不能鎖同一個索引。

  2. insert 覆山,delete 竹伸, update 在事務中都會自動默認加上排它鎖。

  3. 行鎖必須有索引才能實現(xiàn)汹买,否則會自動鎖全表佩伤,那么就不是行鎖了。**

事務

事務特性

ACID

  1. 原子性atomicity晦毙,一個事務為一個不可分割的最小單元生巡,事務中的操作,要么全部成功见妒,要么全部失敗孤荣。

  2. 一致性consistency,事務將數(shù)據(jù)庫從一種一致性轉換到另外一種一致性狀態(tài)须揣,數(shù)據(jù)庫中的數(shù)據(jù)完整性沒有被破壞盐股。

  3. 隔離性isolation,一個事務的執(zhí)行不能被其他事務干擾耻卡。即一個事務內部的操作及使用的數(shù)據(jù)對并發(fā)的其他事務是隔離的疯汁,并發(fā)執(zhí)行的各個事務之間不能互相干擾。

  4. 持久性durability卵酪,事務一旦提交幌蚊,其所做的修改就會永久保存到數(shù)據(jù)庫中。

事務并發(fā)問題

  • 未提交讀(READ UNCOMMITED)臟讀

  • 已提交讀 (READ COMMITED)不可重復讀

  • 可重復讀(REPEATABLE READ)

  • 可串行化(SERIALIZABLE)

MySQL的默認隔離級別為REPEATABLE-READ

show variables like '%isolation%';

間隙鎖(gap鎖)

MySQL中溃卡,可重復讀就已經(jīng)解決了幻讀的問題溢豆,借助的就是間隙鎖。

事務語法

  • 開啟事務:
  1. begin

  2. start transaction(推薦)

  3. begin work

  • 事務回滾:rollback

  • 事務提交:commit

  • 還原點:savepoint point名稱a瘸羡。 rollback to savepoint a 回滾到還原點a

業(yè)務設計

邏輯設計

范式設計

第一大范式:數(shù)據(jù)庫表中的所有字段都只具有單一屬性漩仙,單一屬性的列是由基本數(shù)據(jù)類型所構成的。

第二大范式:表中只有一個業(yè)務主鍵犹赖。

第三大范式:每一個非主屬性既不部分依賴于也不傳遞依賴于業(yè)務主鍵队他。

優(yōu)點:

  1. 可以盡量得減少數(shù)據(jù)冗余

  2. 范式化的更新操作比反范式化更快

  3. 范式化的表通常比反范式化的表更小

缺點:

  1. 對于查詢需要對多個表進行關聯(lián)

  2. 更難進行索引優(yōu)化

反范式設計

為了性能和讀取效率考慮,適當違反數(shù)據(jù)庫設計范式要求峻村,允許存在少量冗余麸折。使用空間來換取時間

優(yōu)點:

  1. 可以減少表的關聯(lián)

  2. 可以更好的進行索引優(yōu)化

缺點:

  1. 存在數(shù)據(jù)冗余及數(shù)據(jù)維護異常

  2. 對數(shù)據(jù)的修改需要更多的成本

物理設計

命名規(guī)范

數(shù)據(jù)庫、表雀哨、字段的命名要遵守可讀性原則,使用下劃線或者大小寫來格式化命名以獲得良好的可讀性

數(shù)據(jù)庫、表雾棺、字段的命名要遵守表意性原則膊夹,對象的名字應該能夠描述它所表示的對象

數(shù)據(jù)庫、表捌浩、字段的命名要遵守長名原則 放刨,盡可能少使用或者不使用縮寫

數(shù)據(jù)類型選擇

當一個列可以選擇多種數(shù)據(jù)類型時

  1. 優(yōu)先考慮數(shù)字類型

  2. 其次是日期、時間類型

  3. 最后是字符類型

  4. 對于相同級別的數(shù)據(jù)類型尸饺,應該優(yōu)先選擇占用空間小的數(shù)據(jù)類型

慢查詢

分析工具: Mysqldumpslow进统,pt_query_digest

索引

索引分類

  1. 普通索引:一個索引只包含單個列,一個表可以有多個單列索引

  2. 唯一索引:索引的值必須唯一浪听,允許有空值

  3. 復合索引:一個索引包含多個列

  4. 聚簇索引(聚集索引):并不是一種單獨的索引類型螟碎,而是一種數(shù)據(jù)存儲方式。具體細節(jié)取決于不同的實現(xiàn)迹栓,InnoDB 的聚簇索引其實就是在同一個結構中保存了 B-Tree 索引(技術上來說是 B+Tree)和數(shù)據(jù)行掉分。

  5. 非聚簇索引:不是聚簇索引,就是非聚簇索引

基礎語法

查看索引:SHOW INDEX FROM 表名

創(chuàng)建索引

  1. CREATE [UNIQUE ] INDEX indexName ON 表名(columnName(length));

  2. ALTER TABLE 表名 ADD [UNIQUE ] INDEX [indexName] ON (columnName(length))

刪除索引

DROP INDEX [indexName] ON 表名;

執(zhí)行計劃

使用EXPLAIN關鍵字可以模擬優(yōu)化器執(zhí)行SQL查詢語句克伊,從而知道MySQL是如何處理SQL語句的酥郭。分析查詢語句或者表結構性能瓶頸

作用

可以查詢到以下信息:

  • 表的讀取順序

  • 數(shù)據(jù)讀取操作的操作類型

  • 哪些索引可以使用

  • 哪些索引被實際使用

  • 表之間的引用

  • 每張表有多少行被優(yōu)化器查詢

詳解

通過explain關鍵字分析的結果由以下列組成。

explain執(zhí)行后的列

id列

描述 select 查詢的序列號,包含一組數(shù)字愿吹,表示查詢中執(zhí)行 select 子句或操作表的順序

根據(jù) ID 的數(shù)值結果可以分成一下三種情況

  • id 相同:執(zhí)行順序由上至下

  • id 不同:如果是子查詢不从,id 的序號會遞增,id 值越大優(yōu)先級越高犁跪,越先被執(zhí)行

  • id 相同和不同:同時存在時椿息,相同id執(zhí)行順序由下至上,不同的大的優(yōu)先執(zhí)行

select_type列

查詢的類型耘拇,用于區(qū)分普通查詢撵颊、聯(lián)合查詢、子查詢等復雜查詢

查詢類型

table列

標識這行數(shù)據(jù)來源于哪張表

type列

顯示的是訪問類型惫叛,結果值從最好到最壞依次是:

system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery >

index_subquery > range > index > ALL

關注的結果值:

system>const>eq_ref>ref>range>index>ALL

一般來說倡勇,得保證查詢至少達到 range 級別,最好能達到 ref嘉涌。

type列各個值含義

  1. system:表只有一行記錄(等于系統(tǒng)表)妻熊,這是 const 類型的特列,平時不會出現(xiàn)仑最,這個也

可以忽略不計

  1. const:表示通過索引一次就找到了

const 用于比較 primary key 或者 unique 索引扔役。因為只匹配一行數(shù)據(jù),所以很快如將主鍵置于 where條件中警医,MySQL 就能將該查詢轉換為一個常量

  1. eq_ref: 唯一性索引掃描亿胸,對于每個索引鍵坯钦,表中只有一條記錄與之匹配。常見于主鍵或唯一索引

掃描

  1. ref: 非唯一性索引掃描侈玄,返回匹配某個單獨值的所有行.

本質上也是一種索引訪問婉刀,它返回所有匹配某個單獨值的行,然而序仙,它可能會找到多個符合

條件的行突颊,所以他應該屬于查找和掃描的混合體

  1. range: 只檢索給定范圍的行,使用一個索引來選擇行。key 列顯示使用了哪個索引一般就是在你的 where 語句中出現(xiàn)了 between潘悼、<律秃、>、in 等的查詢

  2. index : 當查詢的結果全為索引列的時候治唤,雖然也是全部掃描棒动,但是只查詢的索引庫,而沒有去查詢

數(shù)據(jù)肝劲。

  1. all : 將遍歷全表以找到匹配的行

possible_keys 與 key

possible_keys:可能使用的 key

Key:實際使用的索引迁客。如果為 NULL,則沒有使用索引

查詢中若使用了覆蓋索引辞槐,則該索引和查詢的 select 字段重疊

key_len

表示索引中使用的字節(jié)數(shù)掷漱,可以通過該列計算查詢中使用的索引的長度。在不損失精確性的情況下榄檬,長度越短越好

key_len 顯示的值為索引字段的最大可能長度卜范,并非實際使用長度,即 key_len 是根據(jù)表定義計算而得鹿榜,不是通過表內檢索出的

  • key_len 表示索引使用的字節(jié)數(shù)海雪,

  • 根據(jù)這個值,就可以判斷索引使用情況舱殿,特別是在組合索引的時候奥裸,判斷所有的索引字段是否都被查詢用到。

  • char 和 varchar 跟字符編碼也有密切的聯(lián)系,

  • latin1占用 1 個字節(jié)沪袭,gbk 占用 2 個字節(jié)湾宙,utf8 占用3 個字節(jié)。(不同字符編碼占用的存儲空間不同)

    1. 字符類型-索引字段為char類型+不可為Null時

      如果索引定義為char(20) 冈绊,則key_len= 20 * 3(utf-8b編碼)

    2. 字符類型-索引字段為char類型+可為Null時

      如果索引定義為char(20) 侠鳄,則key_len= 20 * 3(utf-8b編碼)+ 1 = 31

      可以為Null,占用一個字節(jié)長度死宣,需要加1

    3. 索引字段為varchar類型+不可為Null時

      Keylen=varchar(n)變長字段+不允許 Null=n*(utf8=3,gbk=2,latin1=1)+2

    4. 索引字段為varchar類型+可為Null時

      Keylen=varchar(n)變長字段+不允許 Null=n*(utf8=3,gbk=2,latin1=1)+2+1

    總結

    字符類型:

    變長字段需要額外的 2 個字節(jié)(VARCHAR 值保存時只保存需要的字符數(shù)伟恶,另加一個字節(jié)來記錄長度(如果列聲明的長度超過 255,則使用兩個字節(jié))毅该,所以 VARCAHR 索引長度計算時候要加 2)博秫,固定長度字段不需要額外的字節(jié)潦牛。

    NULL 需要 1 個字節(jié)的額外空間,所以索引字段最好不要為 NULL,因為 NULL 讓統(tǒng)計更加復雜并且需要額外的存儲空間挡育。

    復合索引有最左前綴的特性罢绽,如果復合索引能全部使用上,則是復合索引字段的索引長度之 和静盅,這也可以用來判定復合索引是否部分使用,還是全部使用寝殴。

    整數(shù)/浮點數(shù)/時間類型的索引長度

    1. NOT NULL=字段本身的字段長度

    2. NULL=字段本身的字段長度+1(因為需要有是否為空的標記蒿叠,這個標記需要占用 1

    個字節(jié))

    1. datetime 類型在 5.6 中字段長度是 5 個字節(jié),datetime 類型在 5.5 中字段長度是 8 個字節(jié)

    ref

    顯示索引的哪一列被用到了

    rows

    根據(jù)表統(tǒng)計信息及索引選用情況蚣常,大致估算出找到所需的記錄需要讀取的行數(shù)市咽。不準確。

    extra

    包含不適合在其它列中展示但十分重要的額外信息抵蚊。

    extra的值說明

    using filesort

    當發(fā)現(xiàn)using filesort時施绎,就是有優(yōu)化的地方了。

    比如聯(lián)合索引是a,b,c三個字段贞绳,查詢時卻是只按照c排序谷醉,就會導致索引失效。

    using Index

    表名使用了覆蓋索引冈闭,避免了訪問表的數(shù)據(jù)行俱尼,效率高。

    覆蓋索引

    select 的數(shù)據(jù)列只用從索引中就能夠取得萎攒,不必讀取數(shù)據(jù)行遇八,MySQL 可以利用索引返回 select 列表中的字段,而不必根據(jù)索引再次讀取數(shù)據(jù)文件,換句話說查詢列要被所建的索引覆蓋耍休。

    如果要使用覆蓋索引刃永,一定要注意 select 列表中只取出需要的列,不可 select *羊精,因為如果將所有字段一起做索引會導致索引文件過大斯够,查詢性能下降。

    SQL優(yōu)化

    優(yōu)化策略

    1. 盡量全值匹配

    2. 最佳左前綴法則(復合索引)园匹。查詢從索引的最左前列開始雳刺,并且不跳過索引中的列。

    3. 不在索引上做任何操作裸违。包括計算掖桦、函數(shù)、類型轉換供汛。會導致索引失效而全表掃描

    4. 范圍條件放最后枪汪。中間有范圍查詢會導致后面的索引列全部失效涌穆。

    5. 覆蓋索引盡量用。

    6. 不等于要慎用雀久。使用不等于會導致索引失效而全表掃描宿稀。需要使用不等于時,使用覆蓋索引赖捌。

    7. Null/not null有影響祝沸。 查詢is not null 時,會導致索引失效越庇。查詢is null時罩锐,如果索引是not null的,就會導致索引失效卤唉,如果不是涩惑,索引有效。解決方案:覆蓋索引

    8. like查詢要當心桑驱。like 以通配符開頭('%abc...')索引失效會變成全表掃描的操作竭恬。

    9. 字符類型加引號。字符串不加單引號會導致索引失效熬的。

    10. or改成union效率高痊硕。

    導入導出數(shù)據(jù)

    load data infile

    select * into OUTFILE 'D:\product.txt' from product_info

    load data INFILE 'D:\product.txt' into table product_info

    load data INFILE '/soft/product3.txt' into table product_info

    show VARIABLES like 'secure_file_priv'

    • secure_file_priv 為 NULL 時,表示限制 mysqld 不允許導入或導出押框。

    • secure_file_priv 為 /tmp 時寿桨,表示限制 mysqld 只能在/tmp 目錄中執(zhí)行導入導出,其他目錄不能執(zhí)行强戴。

    • secure_file_priv 沒有值時亭螟,表示不限制 mysqld 在任意目錄的導入導出。

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末骑歹,一起剝皮案震驚了整個濱河市预烙,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌道媚,老刑警劉巖扁掸,帶你破解...
    沈念sama閱讀 211,561評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異最域,居然都是意外死亡谴分,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,218評論 3 385
  • 文/潘曉璐 我一進店門镀脂,熙熙樓的掌柜王于貴愁眉苦臉地迎上來牺蹄,“玉大人,你說我怎么就攤上這事薄翅∩忱迹” “怎么了氓奈?”我有些...
    開封第一講書人閱讀 157,162評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長鼎天。 經(jīng)常有香客問我舀奶,道長,這世上最難降的妖魔是什么斋射? 我笑而不...
    開封第一講書人閱讀 56,470評論 1 283
  • 正文 為了忘掉前任育勺,我火速辦了婚禮,結果婚禮上罗岖,老公的妹妹穿的比我還像新娘怀大。我一直安慰自己,他們只是感情好呀闻,可當我...
    茶點故事閱讀 65,550評論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著潜慎,像睡著了一般捡多。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上铐炫,一...
    開封第一講書人閱讀 49,806評論 1 290
  • 那天垒手,我揣著相機與錄音,去河邊找鬼倒信。 笑死科贬,一個胖子當著我的面吹牛,可吹牛的內容都是我干的鳖悠。 我是一名探鬼主播榜掌,決...
    沈念sama閱讀 38,951評論 3 407
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼乘综!你這毒婦竟也來了憎账?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,712評論 0 266
  • 序言:老撾萬榮一對情侶失蹤卡辰,失蹤者是張志新(化名)和其女友劉穎胞皱,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體九妈,經(jīng)...
    沈念sama閱讀 44,166評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡反砌,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,510評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了萌朱。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片宴树。...
    茶點故事閱讀 38,643評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖晶疼,靈堂內的尸體忽然破棺而出森渐,到底是詐尸還是另有隱情做入,我是刑警寧澤,帶...
    沈念sama閱讀 34,306評論 4 330
  • 正文 年R本政府宣布同衣,位于F島的核電站竟块,受9級特大地震影響,放射性物質發(fā)生泄漏耐齐。R本人自食惡果不足惜浪秘,卻給世界環(huán)境...
    茶點故事閱讀 39,930評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望埠况。 院中可真熱鬧耸携,春花似錦、人聲如沸辕翰。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,745評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽喜命。三九已至沟沙,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間壁榕,已是汗流浹背矛紫。 一陣腳步聲響...
    開封第一講書人閱讀 31,983評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留牌里,地道東北人颊咬。 一個月前我還...
    沈念sama閱讀 46,351評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像牡辽,于是被迫代替她去往敵國和親喳篇。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,509評論 2 348

推薦閱讀更多精彩內容