1. 程式人生 > >【MySQL資料庫】效能優化之索引及優化(一)

【MySQL資料庫】效能優化之索引及優化(一)

一、Mysql效能優化之影響效能的因素

1.商業需求的影響

不合理的需求造成的資源投入產出,這裡就用一個看上去很簡單的功能分析。
需求:一個論壇帖子的總量統計,附加要求:實時更新。從功能上看來是非常容易實現的,執行一條select count(*)from表名就可以得到結果,但是如果我們採用的不是myisam儲存引擎,而是用的innodb的儲存引擎,如果存放帖子的表中已經有了上千萬的帖子的時候,執行這條語句需要很大的成本。恐怕都不可能在10秒之內完成一次查詢。

 

2.系統架構及實現的影響
所有資料都是適合在資料庫存放嗎?資料庫為我們提供了太多的功能,反而讓很多並不是臺瞭解資料庫的人錯誤的使用了資料庫的很多並不是太擅長或者對效能影響很大的功能,最後卻都怪到了資料庫上。

以下幾類資料都是不適合在資料庫中存放的

(1)二進位制多媒體的資料包括(圖片,視訊,音訊)和其他一些相關的二進位制檔案,將二進位制多媒體資料存放在資料庫中,一個問題是資料庫空間資源耗用非常的嚴重,另外一個問題是這些資料庫的儲存很消耗資料庫主機的cpu等資源,這些資料的處理本不是資料庫的優勢
(2)超大的文字資料
對於5.0.3之前的mysql版本來說,varchar型別的資料最長智慧存放225個位元組,如果需要儲存更長的文字資料到一個欄位,我們就必須使用text型別最大可以存放64K的欄位,甚至更大的longtext型別最大4G從5.0.3版本開始varchar型別的最大長度被調整到了64KB了,所以超大文字資料存放在資料庫中不僅會帶來效能低下的問題,還好帶來空間佔用浪費的問題
(3)查詢語句對效能的影響
Sql語句優劣是對效能有影響的,每一個sql語句在優化之前和優化之後的效能差異也是各個不同。
首先先插入兩萬行資料測試,之後會用的到,指令碼如下:

 

#!/bin/bash
HOSTNAME="localhost"
PORT="3306"
USERNAME="root"
PASSWORD="pwd123"
DBNAME="test1"
TABLENAME="tb1"
#create database
mysql -h ${HOSTNAME} -P${PORT} -u${USERNAME} -p${PASSWORD} -e "drop database if exists ${DBNAME}"
create_db_sql="create database if not exists ${DBNAME}"
mysql -h ${HOSTNAME} -P${PORT} -u${USERNAME} -p${PASSWORD} -e"${create_db_sql}"
#create table
create_table_sql="create table if not exists ${TABLENAME}(stuid int not null primary key,stuname varchar(20) not null,stusex char(1) 
not null,cardid varchar(20) not null,birthday datetime,entertime datetime,address varchar(100)default null)"
mysql -h ${HOSTNAME} -P${PORT} -u${USERNAME} -p${PASSWORD} ${DBNAME} -e"${create_table_sql}"
#insert data to table
i="1"
while [ $i -le 20000 ]
do
insert_sql="insert into ${TABLENAME}  values($i,'zhangsan','1','21276387261874682','1999-10-10','2017-10-24','beijingchangpingqu')"
mysql -h ${HOSTNAME} -P${PORT} -u${USERNAME} -p${PASSWORD} ${DBNAME} -e"${insert_sql}"
let i++
done
#select data
select_sql="select count(*)from${TABLENAME}"
mysql -h ${HOSTNAME} -P${PORT} -u${USERNAME} -p${PASSWORD} ${DBNAME} -e"${select_sql}"

 

 

 

 

執行過程及執行結束如下:

以上圖中其中的以下欄位意思是:MySQL:[警告]在命令列介面使用密碼可能是不安全的。

 

mysql: [Warning] Using a password on the command line interface can be insecure.

 

插入兩萬行資料後,可以這麼檢視

 

mysql> select count(*) from test1.tb1;
+----------+
| count(*) |
+----------+
|    20000 |
+----------+
1 row in set (0.01 sec)

 

3.執行sql語句時可以用explain來檢視執行計劃:

 

mysql> explain select stuid,stuname,cardid from test1.tb1 where stuid between 3000 and 5000 order 
by stuid desc limit 20\G

 

 

 

 

 

 

 

還可以開啟mysql的profiping功能,來檢視sql的實際執行計劃

 

mysql> set profiling=1;
select stuid,stuname,cardid from test1.tb1 where stuid between 3000 and 5000 order by stuid desc 
limit 5\G

 

 


4、資料庫schema設計對效能的影響
5、硬體選擇對效能的影響

 

 

 

二、mysql效能優化之-索引
如果正確的合理設計並且使用索引的mysql是一架飛機,那麼沒有設計和使用索引的mysql就是一輛自行車,對於沒有索引的表,單表查詢可能幾十萬資料就是瓶頸,而通常大型網站一天就會產生幾十萬甚至幾百萬的資料,沒有設定索引會非常的慢。

1.為了測試我們給tb1表中插入一條不相同的資料。

 

mysql> insert into test1.tb1 values(20001,'admin','0','12322112123332','1999-1-1','2019-9-1','ppppppppppp');
Query OK, 1 row affected (0.00 sec)

 

例1:stuname上沒有建立索引的情況

 

mysql> explain select stuid,stuname,stusex,cardid,entertime from test1.tb1 where stuname='admin'\G

 

 

 

 

 

例2:我們給stuname上建立索引再次檢視。

 

mysql> create index index_stuname on test1.tb1(stuname);

 

 

在查詢stuname=”admin”的記錄的時候,如果stuname上已經建立了索引,mysql無須任何掃描全表,即準確可找到該記錄,相反mysql會掃描所有的記錄,所以在資料庫表中,對欄位建立索引可以大大的提高查詢的速度

 

索引的型別
1)普通索引這是最基本的索引,它沒有任何的限制

 

Create index indexname on 表(xxx)

 

2)唯一索引:它和前面的普通索引相似,不同的就是索引列的值必須唯一,但允許空值,空值指的就是null如果是組合索引,組合列的值必須是唯一的。

 

Create unique index indexname on 表(xxx)

 

 

3)組合索引:為了進一步的提升mysql的效率,就要考慮建立組合索引

 

列如建立一個表,包含如下欄位

 

Create table mytable(id int not null,uname varchar(16)not null,city varchar(50) not ntll,age 
int not null);

 

 

將uname,city,age建在一個索引裡

 

Create index uname_city_age on mytable(uname,ctiy,age)

 

4、全文索引:只用於myisam表對文字進行索引,欄位包括char varchar text不過切記對大容量的資料表,生成全文索引的是一個非常消耗時間硬碟的做法

 

Create fulltext index indexname on tablename(column)

 

檢視索引

 

mysql> show index from test1.tb1;

 

 

mysql> show keys from test1.tb1;

 

三、mysql效能優化-,慢查詢分析、優化索引和配置
1)效能瓶頸定位
show 命令  慢查詢日誌 explain分析查詢 profiling分析查詢
2)索引及查詢優化
3)配置優化
mysql資料庫最常見的兩個瓶頸的CPU和I/O的瓶頸,cpu在飽和的時候一般發生在資料裝入記憶體或從磁碟上讀取資料的時候,磁碟I/O瓶頸發生在裝入資料遠大於記憶體容量的時候,如果應用分佈在網路上,那麼查詢量相當大的時候那麼瓶頸就會出現在網路上,我們可以用mpstat,iostat,sar和vmstat來檢視系統的效能狀態
使用mpstat來檢視系統的效能狀態如下:

上圖我寫的是mpstat 3 6這個意思是3秒執行1次 一共6次 然後紅方框的idle顯示的是空閒度,從這個圖中可以看出此時很空閒,那麼我們來給它點壓力來測試。(我這邊插入10萬行的資料,然後再次看它的變化)

以上圖中正在執行插入10萬行的資料!


4)show命令可以檢視mysql狀態及變數,找到系統的瓶頸

 

mysql> show variables;
mysql> show global status;

 

 

 

 

 

同時也可以這麼檢視,都是一樣的

 

[[email protected] ~]# mysqladmin variables -uroot -ppwd123
[[email protected] ~]# mysqladmin extended-status -uroot -ppwd123

更多的show命令可以通過mysql>help show來檢視


開啟慢查詢日誌
在配置檔案中my.cnf下加入3個配置引數,並重啟mysql服務
檢視慢查詢日誌是否開啟

mysql> show global variables like "%slow_query_log%"

 

 

 

 

 

開啟慢查詢日誌,開啟主配置檔案,新增如下:


 

重啟mysql服務再次檢視慢查詢日誌

 

mysql> show global variables like "%slow_query_log%"



檢視查詢的時間以及設定查詢的時間

 

 

 

 

mysql> show global variables like "%long%";

 

 

 

 

 

這裡我們設定時間為0.001秒,修改主配置檔案新增如下:

修改完成後重啟mysql服務再次檢視查詢時間

 

mysql> show global variables like "%long%";

 

 

 

 

 

我們可以通過開啟log檔案檢視得知哪些sql執行效率低下
我們做以下操作,查庫,查表,然後在看log檔案

檢視log檔案

以下顯示的就一條慢查詢,如何優化呢

 

1、在entertime列上建立索引優化查詢

 

mysql> create index index_entertime on test1.tb1(entertime);


2、explain分析查詢
使用explain關鍵字可以模擬優化器執行sql查詢語句,從而知道mysql是如何處理你的sql語句的,這可以幫你分析你的查詢語句或是表結構效能瓶頸,通過explain命令可以得到

 

 

 

 

mysql> explain select * from test1.tb1 where stuname='yankerp'\G


explain欄位:
table:顯示這一行資料是關於那張表的
type:這是最重要的欄位之一,顯示查詢使用了何種型別。從最好的到最差的連線型別位system、const、eq_reg、ref、range、index和all
possible_keys:顯示可能應用在這張表中的索引。如果為空,沒有可能的索引
key:實際使用的索引,如果為null,則沒有使用索引。
key_len:使用的索引長度,在不損失的情況下,長度越短越好
ref:顯示索引的哪一列被使用了,如果可能的話,是一個常數
rows:mysql認為不許檢索的用來返回請求資料的行數
extra:關於mysql如何解析查詢的額外資訊
從上面的explain模擬優化器中執行sql語句來看是由索引查詢的。
3profiling分析查詢
通過慢日誌查詢可以知道那些sql語句執行效率低下,通過explain我可以得知sql語句的具體執行情況,索引使用等,還可以結合show命令檢視執行狀態,可以通過profiling命令得到更準確的sql執行消耗系統資源的資訊。
profiling預設是關閉的。可以通過以下語句檢視
mysql> show variables like '%profiling%';  //off代表未開啟

 

 

 

開啟profiling功能:mysql>set profiling=1;執行需要測試的sql語句:

 

mysql> select @@profiling;

 

 

 

 

 

4、執行要測試的sql語句

 

mysql> select * from test1.tb1 where stuname='admin' and entertime='2019-09-01';
mysql> show profiles\G   //可以得到被執行語句的id

 

mysql> show profile for query 6; //得到對應執行sql語句的詳細資訊


 

 

測試完成後,記得關閉除錯功能,以免影響到資料庫的正常使用

 

mysql> set profiling=0;
Query OK, 0 rows affected, 1 warning (0.00 sec)

 

 

 

 

希望對您有所幫助,後續更新。再見