1. 程式人生 > >MySQL優化技術(二)

MySQL優化技術(二)

(五)常用SQL優化

1.預設情況,在使用group by 分組查詢時,會先分組,其後還會預設對組內其他條件進行預設的排序,可能會降低速度。這與在查詢中指定order by col1, col2類似。

如果查詢中包括group by但使用者想要避免排序結果的消耗,則可以使用order by null禁止排序。

例子:

 

2.儘量使用左連線(或右連線)來替代普通多表聯查。因為使用JOIN,MySQL不需要在記憶體中建立臨時表

   select * from dept,emp where dept.deptno=emp.deptno; 【普通聯表查詢】

   select * from dept left join

 empon dept.deptno=emp.deptno;  【左外連線,效率更高】

3.如果想要在含有or的查詢語句中利用索引,則or之間的每個條件列都必須用到索引,如果沒有索引,則應該考慮增加索引;

   select * from 表名 where 條件1=‘t1’ or 條件2=‘t2’;

4.選擇合適的儲存引擎

在開發中,我們經常使用的儲存引擎 MyISAM / INNODB / Memory

1)MyISAM儲存: 如果表對事務要求不高,同時是以查詢和新增為主的,我們考慮使用MyISAM儲存引擎,比BBS中的發帖表,回覆表

2)INNODB儲存MySQL 5.5以上預設): 對事務要求高

,儲存的資料都是重要資料,我們建議使用INNODB,比如訂單表,賬號表

【引申】 MyISAM 和 INNODB的主要區別

①MyISAM不支援事務;而INNODB支援事務;

②MyISAM批量查詢的速度比INNODB快(因為INNODB在插入資料時預設會排序);

③MyISAM支援全文索引;而INNODB不支援;

④MyISAM是表鎖;而INNODB在有索引時,預設為行鎖,無索引時,為行鎖;

⑤MyISAM 不支援外來鍵;INNODB支援外來鍵;(在PHP開發中,通常不設定外來鍵,通常是在程式中保證資料的一致)

3)Memory儲存,比如我們資料變化頻繁不需要入庫(重啟mysql後,資料會清空),同時又頻繁的查詢和修改

,我們考慮使用memory,資料全部在記憶體中,速度極快


4)MySQL行級鎖、表級鎖、頁級鎖

①表級:引擎 MyISAM預設。直接鎖定整張表,在你鎖定期間,其它程序無法對該表進行寫操作。如果你是寫鎖。則其它程序則讀也不允許;

②行級:有索引時,引擎 INNODB預設(無索引時,為表級鎖)。僅對指定的記錄進行加鎖,這樣其它程序還是可以對同一個表中的其它記錄進行操作;

③頁級:引擎 BDB預設。表級鎖速度快,但衝突多,行級衝突少,但速度慢。所以取了折衷的頁級,一次鎖定相鄰的一組記錄。

各自的特點

①表級鎖:開銷小,加鎖快;不會出現死鎖;鎖定粒度大,發生鎖衝突的概率最高,併發度最低。

②行級鎖:開銷大,加鎖慢;會出現死鎖;鎖定粒度最小,發生鎖衝突的概率最低,併發度也最高。

③頁面鎖:開銷和加鎖時間界於表鎖和行鎖之間;會出現死鎖;鎖定粒度界於表鎖和行鎖之間,併發度一般。

【補充】InnoDB使用行鎖定,BDB使用頁鎖定。對於這兩種儲存引擎,都可能存在死鎖。這是因為,SQL語句處理期間InnoDB自動獲得行鎖定和BDB獲得頁鎖定,而不是在事務啟動時獲得

Ⅰ)MySQL表級鎖有兩種模式

表共享讀鎖(Table Read Lock)表獨佔寫鎖(Table Write Lock)。什麼意思呢,就是說對MyISAM表進行讀操作時,它不會阻塞其他使用者對同一表的讀請求,但會阻塞 對同一表的寫操作;而對MyISAM表的寫操作,則會阻塞其他使用者對同一表的讀和寫操作。

MyISAM表的讀和寫是序列的,即在進行讀操作時不能進行寫操作,反之也是一樣。但在一定條件下MyISAM表也支援查詢和插入的操作的併發進行,其機制是通過控制一個系統變數(concurrent_insert)來進行的:

①當其值設定為0時,不允許併發插入

②當其值設定為1時,如果MyISAM表中沒有空洞(即表中沒有被刪除的行),MyISAM允許在一個程序讀表的同時,另一個程序從表尾插入記錄

③當其值設定為2時,無論MyISAM表中有沒有空洞,都允許在表尾併發插入記錄

MyISAM鎖排程是如何實現的呢,這也是一個很關鍵的問題。例如,當一個程序請求某個MyISAM表的讀鎖,同時另一個程序也請求同一表的寫鎖,此時MySQL將會如優先處理程序呢?通過研究表明,寫程序將先獲得鎖(即使讀請求先到鎖等待佇列)。但這也造成一個很大的缺陷,即大量的寫操作會造成查詢操作很難獲得讀鎖,從而可能造成永遠阻塞。所幸我們可以通過一些設定來調節MyISAM的排程行為。我們可通過指定引數,設定set low_priority_updates=1,使優先順序降低。

Ⅱ)InnoDB有兩種模式的行鎖 

1)共享鎖:允許一個事務去讀一行,阻止其他事務獲得相同資料集的排他鎖。

   Select * from table_name where ......lock in share mode;

2)排他鎖:允許獲得排他鎖的事務更新資料,阻止其他事務取得相同資料集的共享讀鎖和  排他寫鎖。

   select * from table_name where.....for update;

InnoDB行鎖是通過給索引項加鎖來實現的,即只有通過索引條件檢索資料,InnoDB才使用行級鎖,否則將使用表鎖

Ⅲ)插入時,更新效能優化的幾個重要引數:

① bulk_insert_buffer_size  批量插入快取大小

    這個引數是針對MyISAM儲存引擎來說的.適用於在一次性插入100-1000+條記錄時, 提高效率.預設值是8M.可以針對資料量的大小,翻倍增加;

② concurrent_insert 併發插入

當表沒有空洞(刪除過記錄), 在某程序獲取讀鎖的情況下,其他程序可以在表尾部進行插入;

值可以設0不允許併發插入, 1當表沒有空洞時, 執行併發插入, 2不管是否有空洞都執行併發插入(預設是1 針對表的刪除頻率來設定);

③ delay_key_write 針對MyISAM儲存引擎,延遲更新索引

    意思是說,update記錄時,先將資料up到磁碟,但不up索引,將索引存在記憶體裡,當表關閉時,將記憶體索引,寫到磁碟. 值為 0不開啟, 1開啟. 預設開啟.

④ delayed_insert_limit, delayed_insert_timeout, delayed_queue_size

延遲插入, 將資料先交給記憶體佇列, 然後慢慢地插入.但是這些配置,不是所有的儲存引擎都支援, 目前來看, 常用的InnoDB不支援, MyISAM支援.根據實際情況調大, 一般預設夠用了

5.能用deciaml 的地方,儘量不要用float

【引申】float、double和decimal的區別:

float:浮點型,佔4個位元組,數值範圍為-3.4E38~3.4E38(7個有效位

double:雙精度實型,佔8個位元組,數值範圍-1.7E308~1.7E308(15個有效位

decimal:數字型,佔16個位元組,不存在精度損失,常用於銀行帳目計算。(28個有效位

decimal(a,b):

a——指定指定小數點左邊和右邊可以儲存的十進位制數字的最大個數,最大精度38。

b——指定小數點右邊可以儲存的十進位制數字的最大個數。小數位數必須是從 0 到 a之間的值。預設小數位數是 0。

6.對於儲存引擎是MyISAM的資料庫,如果經常做刪除和修改記錄的操作,要定時執行optimize table table_name;功能對錶進行碎片整理

(六)分表技術

1.水平分割(分表)

分表是將一個大表按照一定的規則分解成多張具有獨立儲存空間的實體表,我們可以稱為子表,每個表都對應三個檔案,MYD資料檔案,MYI索引檔案,frm表結構檔案。這些子表可以分佈在同一塊磁碟上,也可以在不同的機器上。app讀寫的時候根據事先定義好的規則得到對應的子表名,然後去操作它。

簡單理解:將一張大表,分割成多個數據型別與大表相同的子表,在訪問時,根據事先定義好的規則等到對應的表名,然後去操作;

2.垂直分割(分割槽)

分割槽和分表相似,都是按照規則分解表。不同在於分表將大表分解為若干個獨立的實體表,而分割槽是將資料分段劃分在多個位置存放,可以是同一塊磁碟也可以在不同的機器。分割槽後,表面上還是一張表,但資料雜湊到多個位置了。app讀寫的時候操作的還是大表名字,db自動去組織分割槽的資料。

簡單理解:是將一張大表的某(幾)列,提取成一張單獨的表。一般情況兩者的關係是一對一;

3.分表的幾種方式

1)mysql叢集

它並不是分表,但起到了和分表相同的作用。叢集可分擔資料庫的操作次數,將任務分擔到多臺資料庫上。叢集可以讀寫分離,減少讀寫壓力。從而提升資料庫效能。

2)自定義規則分表

大表可以按照業務的規則來分解為多個子表。通常為以下幾種型別,也可自己定義規則。

①Range(範圍):這種模式允許將資料劃分不同範圍。例如可以將一個表通過年份劃分成若干個分割槽。

②Hash(雜湊):這中模式允許通過對錶的一個或多個列的Hash Key進行計算,最後通過這個Hash碼不同數值對應的資料區域進行分割槽。例如可以建立一個對錶主鍵進行分割槽的表。

③Key(鍵值):上面Hash模式的一種延伸,這裡的Hash Key是MySQL系統產生的。

④List(預定義列表):這種模式允許系統通過預定義的列表的值來對資料進行分割。

⑤Composite(複合模式):以上模式的組合使用 

3)利用merge儲存引擎來實現分表

這裡不做詳解,因為有一個更強大的技術Mycat,可以幫我實現各種分庫分表!

(七)mysql引數調優

主要是通過修改mysql的my.ini配置檔案

1.如果是InnoDB引擎:

  innodb_additional_mem_pool_size= 64M

  innodb_buffer_pool_size= 1G

2.如果是MyISAM引擎:

調整key_buffer_size

當然調整引數還是要看狀態,用show status語句可以看到當前狀態,以決定改調整哪些引數。

3.還可以調整最大連線數

    # connection limit has been reached.

    max_connections=1000

(八)讀寫分離

參照《使用Spring配置多資料來源,實現讀寫分離( MySQL實現主從複製)一文,