Mysql數據庫優化
1. 優化概述
存儲層:存儲引擎、字段類型選擇、范式設計
設計層:索引、緩存、分區(分表)
架構層:多個mysql服務器設置,讀寫分離(主從模式)
sql語句層:多個sql語句都可以達到目的的情況下,要選擇性能高、速度快的sql語句
2. 存儲引擎
什么是存儲引擎:
我們使用的數據是通過一定的技術存儲在數據當中的,數據庫的數據是以文件形式組織的硬盤當中的。技術不只一種,並且每種技術有自己獨特的性能和功能體現。
存儲數據的技術和其功能的合並就稱為“存儲引擎”。
在mysql中經常使用的存儲引擎:Myisam或Innodb等等。
借用網上的一張圖片
數據庫的數據存儲在不同的存儲引擎里邊,所有的特性就與當前的存儲引擎有一定關聯。
需要按照項目的需求、特點選擇不同的存儲引擎。
查看mysql中支持的全部存儲引擎:
2.1 innodb
數據庫每個數據表的數據設計三方面信息:表結構、數據、索引
技術特點:支持事務、行級鎖定、外鍵
1)表結構、數據、索引的物理存儲
創建一個innodb數據表:
該類型 數據、索引 的物理文件位置:
所有innodb表的數據和索引信息都存儲在以下ibdata1文件中
給innodb類型表 的數據和索引創建自己對應的存儲空間:
默認情況下每個innodb表的 數據和索引 不會創建單獨的文件存儲
設置變量,使得每個innodb表有獨特的數據和索引 存儲文件:
重新創建數據表的話數據表就對應有單獨的數據和索引文件:
(后期無論innodb_file_per_table的設置狀態如何變化,order2的數據和索引都有獨立的存儲位置)
2)數據存儲順序
innodb表數據的存儲是按照主鍵的順序排列每個寫入的數據。
該特點決定了該類型表的寫入操作較慢。
3)事務、外鍵
該類型數據表支持事務、外鍵
事務:把許多寫入(增、改、刪)的sql語句捆綁在一起,要么執行、要么不執行
事務經常用於與“錢”有關的方面。
四個特性:原子、一致、持久、隔離
具體操作:
start transaction;
許多寫入sql語句
sql語句有問題
rollback;回滾
commit;提交
rollback和commit只能執行一個
外鍵:兩個數據表A和B,B表的主鍵是A表的普通字段,在A表看這個普通的字段就是該表的“外鍵”,外鍵的使用有”約束”。
約束:以上兩個表,必須先寫B表的數據,再寫A表的數據
並且 A表的外鍵取值必須來之B表的主鍵id值,不能超過其范圍。
真實項目里邊很少使用“外鍵”,因為有約束。
4) 並發性
該類型表的並發性非常高
多人同時操作該數據表
為了操作數據表的時候,數據內容不會隨便發生變化,要對信息進行“鎖定”
該類型鎖定級別為:行鎖。只鎖定被操作的當前記錄。
2.2 Myisam
1) 結構、數據、索引獨立存儲
該類型的數據表 表結構、數據、索引 都有獨立的存儲文件:
創建Myisam數據表
存在data文件夾中三個文件分別對應的是:、
*.frm:表結構文件
*.MYD:表數據文件
*.MYI:表索引文件
每個myisam數據表的 結構、數據、索引 都有獨立的存儲文件
特點:獨立的存儲文件可以單獨備份、還原。
2) 數據存儲順序
myisam表數據的存儲是按照自然順序排列每個寫入的數據。
該特點決定了該類型表的寫入操作較快。
3) 並發性
該類型並發性較低
該類型的鎖定級別為:表鎖
4)壓縮機制
如果一個數據表的數據非常多,為了節省存儲空間,需要對該表進行壓縮處理。
復制當前數據表的數據:
不斷復制使得數據表的數據變為500多萬條:
對應的存儲500萬條信息的文件的物理大小為將近100多兆:
開始壓縮數據表的數據
壓縮:myisampack.exe 表名
重建索引:myisamchk.exe -rq 表名
解壓縮:myisamchk.exe --unpack 表名
表信息被壓縮的75%的空間:
壓縮后的大小為:
數據表有壓縮,但是索引沒有了,需要重建索引。
刷新數據表:flush table 表名
但是出現了這么一個情況:
壓縮的數據表是只讀表,不能寫信息:(read only)
總結:壓縮的數據表有特點:不能頻繁的寫入操作,只是內容固定的數據表可以做壓縮,存儲全國地區信息的數據表
如果必須要寫數據:就解壓該數據表,寫入數據,再壓縮
innodb存儲引擎:適合做修改、刪除
Myisam存儲引擎:適合做查詢、寫入
3.3 Archive
歸檔型存儲引擎,該引擎只有寫入、查詢操作,沒有修改、刪除操作
比較適合存儲“日志”性質的信息。
3.4 memory
內存型存儲引擎,操作速度非常快速,比較適合存儲臨時信息,
服務器斷電,給存儲引擎的數據立即丟失。
3. 存儲引擎的選擇
Myisam和innodb
網站大多數情況下“讀和寫”操作非常多,適合選擇Myisam類型
例如 dedecms、phpcms內容管理系統(新聞網站)、discuz論壇
網站對業務邏輯有一定要求(辦公網站、商城)適合選擇innodb
Mysql5.5默認存儲引擎都是innodb的
4. 字段類型選擇
4.1 盡量少的占據存儲空間
int整型
年齡:tinyint(1) 0-255之間
烏龜年齡: smallint(2)
mediumint(3)
int(4)
bigint(8)
時間類型date
time() 時分秒
datetime() 年月日 時分秒
year() 年份
date() 年月日
timestamp() 時間戳(1970-1-1到現在經歷的秒數)
根據不同時間信息的范圍選取不同類型的使用
4.2 數據的整合最好固定長度
char(長度)
固定長度,運行速度快
長度:255字符限制
varchar(長度)
長度不固定,內容比較少要進行部位操作,該類型要保留1-2個字節保存當前數據的長度
長度:65535字節限制
存儲漢字,例如字符集utf8的(每個漢字占據3個字節),最多可以存儲65535/3-2字節
存儲手機號碼:char(11)
4.3 信息最好存儲為整型的
時間信息可以存儲為整型的(時間戳)
select from_unixstamp(時間戳) from 表名
set集合類型 多選:set(‘籃球’,’足球’,’棒球’,’乒乓球’);
enum枚舉類型 單選: enum(‘男’,’女’,’保密’);
推薦使用set和enum類型,內部會通過整型信息參數具體計算、運行。
ip地址也可以變為整型信息進行存儲(mysql內部有算法,把ip變為數字):
mysql: inet_aton(ip) inet_ntoa(數字)
php: ip2long(ip) long2ip(數字)
總結2:
1. 存儲引擎
數據存儲技術格式
Myisam
innodb
2. 字段類型選擇
原則:占據空間小、數據長度最好固定、數據內容最好為整型的
5. 逆范式
數據庫設計需要遵守三范式。
兩個數據表:商品表Goods、分類表Category
Goods: id name cat_id price
101 iphone6s 2003 6000
204 海爾冰箱 4502 2000
......
Category: cat_id name goods_num
2003 手機
4502 冰箱
.....
需求:
計算每個分類下商品的數量是多少?
select c.cat_id,c.name,count(c.*) from category as c left join goods as g on g.cat_id=c.cat_id;
上邊sql語句是一個多表查詢,並且還有count的聚合計算。
如果這樣的需求很多,類似的sql語句查詢速度沒有優勢,
如果需要查詢速度提升,最好設置為單表查詢,並且沒有聚合計算。
解決方法是:給Category表增加一個商品數量的字段goods_num
那么優化后的sql語句:
select cat_id,name,goods_num from category;
但是需要維護額外的工作:goods商品表增加、減少數據都需要維護goods_num字段的信息。
以上對經常使用的需求做優化,增加一個goods_num字段,該字段的數據其實通過goods表做聚合計算也可以獲得,該設計不滿足三范式,因此成為”逆范式”.
三范式:
① 一范式:原子性,數據不可以再分割
② 二范式:數據沒有冗余
order goods
ida 編號1 下單時間 商品信息1 商品價格 商品描述 商品產地
idb 編號1 下單時間 商品信息2 商品價格 商品描述 商品產地
idb 編號1 下單時間 商品信息3 商品價格 商品描述 商品產地
訂單表 id 編號1 下單時間 g1,g2,g3
③ 三范式
數據表每個字段與當前表的主鍵產生直接關聯(非間接關聯)
userid name height weight orderid 編號 訂單時間
優化:
userid name height weight
userid orderid
orderid 編號 訂單時間
6. 索引index
索引是優化數據庫設計,提升數據庫性能非常顯著的技術之一。
各個字段都可以設計為索引,經常使用的索引為主鍵索引primary key
索引可以明顯提升查詢sql語句的速度
6.1 是否使用索引速度的差別
對一個沒有索引的數據表進行數據查詢操作:
沒有索引,查詢一條記錄消耗1.49s的時間:
一旦設置索引,再做數據查詢,時間提升是百倍至千倍級的:
6.2 什么是索引
索引本身是一個獨立的存儲單位,在該單位里邊有記錄着數據表某個字段和字段對應的物理空間。
索引內部有算法支持,例如二分查找,可以使得查詢速度非常快。
有了索引,我們根據索引為條件進行數據查詢速度就非常快
① 索引本身有”算法”支持,可以快速定位我們要找到的關鍵字(字段)
② 索引字段與物理地址有直接對應,幫助我們快速定位要找到的信息
一個數據表的全部字段都可以設置索引
6.3 索引類型
四種類型:
① 主鍵 primary key
auto_increment必須給主鍵索引設置
信息內容要求不能為null,唯一
② 唯一 unique index
信息內容不能重復
③ 普通 index
沒有具體要求
④ 全文 fulltext index
myisam數據表可以設置該索引
復合索引:索引關聯的字段是多個組成的,該索引就是復合索引。
1) 創建索引
創建: 創建表時;創建數據表后添加並設置各種索引:
2)刪除索引
alter table 表名 drop primary key; //刪除主鍵索引
注意:該主鍵字段如果存在auto_increment屬性,需要先刪除之
alter table 表名 modify 主鍵 int not null comment ‘主鍵’;
去除數據表主鍵字段的auto_increment屬性:
禁止刪除主鍵,原因是內部有auto_increment屬性:
alter table 表名 drop index 索引名稱; //刪除其他索引(唯一、普通、全文)
6.4 執行計划explain
針對查詢語句設置執行計划,當前數據庫只有查詢語句支持執行計划。
每個select查詢sql語句執行之前,需要把該語句需要用到的各方面資源都計划好
例如:cpu資源、內存資源、索引支持、涉及到的數據量等資源
查詢sql語句真實執行之前所有的資源計划就是執行計划。
我們討論的執行計划,就是看看一個查詢sql語句是否可以使用上索引。
具體操作:
explain 查詢sql語句\G;
一條sql語句在沒有執行之前,可以看一下執行計划。
主鍵索引刪除后,該查詢語句的執行計划就沒有使用索引(執行速度、效率低)
6.5 索引適合場景
1) where查詢條件
where 之后設置的查詢條件字段都適合做索引。
2) 排序查詢
order by 字段 //排序字段適合做索引
where 和 order by后邊的條件字段都可以適當設置索引
3) 索引覆蓋
給ename和job設置一個復合索引:
索引覆蓋:我們查詢的全部字段(ename,job)已經在索引里邊存在,就直接獲取即可
不用到數據表中再獲取了。因此成為”索引覆蓋”
該查詢速度非常快,效率高,該索引也稱為”黃金索引”
索引本身需要消耗資源的(空間資源、升級維護困難):
4) 連接查詢
join join on
goods : id name cat_id ...
category: cat_id name ...
在Goods數據表中給外鍵/約束字段cat_id設置索引,可以提高聯表查詢的速度
6.6 索引原則
1)字段獨立原則
select * from emp where empno=1325467; //empno條件字段獨立
select * from emp where empno+2=1325467; //empno條件字段不獨立
只有獨立的條件字段才可以使用索引
獨立的條件字段可以使用索引:
不獨立的條件字段不給使用索引:
2) 左原則
模糊查詢,like % _
%:關聯多個模糊內容
_: 關聯一個模糊內容
select * from 表名 like “beijing%”; //使用索引
select * from 表名 like “beijing_”; //索引索引
查詢條件信息在左邊出現,就給使用索引
XXX% YYY_ 使用索引
%AAA% _ABC_ %UUU 不使用索引
沒有使用索引(中間條件查詢):
3) 復合索引
ename復合索引 內部有兩個字段(ename,job)
① ename(前者字段)作為查詢條件可以使用復合索引
② job(后者字段)作為查詢條件不能使用復合索引
復合索引的第一個字段可以使用索引:
復合索引的其余字段不能使用索引:
如果第一個字段的內容已經確定好,第二個字段也可以使用索引:
4) OR原則
OR左右的關聯條件必須都具備索引 才可以使用索引:
or的左右,只有一個有索引,導致整體都沒有的使用:
總結3:
1. 逆范式
2. 索引
索引是數據表的某個字段作為關鍵字,該關鍵字與信息的物理地址進行對應
通過索引查找信息,內部有算法,速度有保證,索引信息找到就找到記錄的物理地址
進而獲得該記錄信息
索引類型:主鍵、唯一、普通、全文
創建:創建數據表時設置索引
給已有數據表設置索引
刪除:alter table 表名 drop primary key;
//刪除主鍵,需要先刪除auto_incremenet
alter table 表名 drop index 索引名
3. exlain執行計划
針對 查詢sql語句 可以設置執行計划
4. 索引適合場景:where、order by、索引覆蓋、連接查詢(約束字段)
5. 索引使用原則:左原則、字段獨立、復合索引、or原則