mysql 數據庫優化第一篇(基礎)


 

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原則 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM