mysql優化之二(SQL語句優化)

更多內容請訪問PHP圖庫(www.phptuku.com)
(一)sql語句的類型

 1.DQL(數據查詢語言):select
 2.DDL(數據定義語言):create、drop、alter
 3.DML(數據操作語言):insert、delete、update
 4.DCL(數據控制語言):grant、revoke
 5.TCL(事務控制語言):rollback、savepoint、commit

(二)mysql優化的一般步驟

  • 通過show status …命令查看各種sql執行頻率
  • 定位執行效率較低的語句(重點select慢查詢)
  • 通過explain分析低效率的sql語句的執行情況
  • 確定問題並採取相應的優化措施

1.查看數據庫當前狀態,show參數,主要關注的是Com開頭的指令

show status like 'Com_某某'; //某某所執行的次數
mysql> show status like 'Com%';//顯示當前控制檯的情況
+---------------------------+-------+
| Variable_name             | Value |
+---------------------------+-------+
| Com_admin_commands        | 0     |
| Com_assign_to_keycache    | 0     |
| Com_alter_db              | 0     |
| Com_alter_db_upgrade      | 0     |
| Com_alter_event           | 0     |
| Com_alter_function        | 0     |
| Com_alter_procedure       | 0     |
| Com_alter_server          | 0     |
| Com_alter_table           | 0     |
| Com_alter_tablespace      | 0     |
| Com_analyze               | 0     |
| Com_begin                 | 0     |
| Com_binlog                | 0     |
| Com_call_procedure        | 0     |
| Com_change_db             | 0     |
| Com_change_master         | 0     |
| Com_check                 | 0     |
| Com_checksum              | 0     |
| Com_commit                | 0     |
| Com_create_db             | 0     |
| Com_create_event          | 0     |
| Com_create_function       | 0     |
| Com_create_index          | 0     |
| Com_create_procedure      | 0     |
| Com_create_server         | 0     |
| Com_create_table          | 0     |
| Com_create_trigger        | 0     |
| Com_create_udf            | 0     |
| Com_create_user           | 0     |
| Com_create_view           | 0     |
| Com_dealloc_sql           | 0     |
| Com_delete                | 0     |   //顯示刪除所執行的次數
| Com_delete_multi          | 0     |
| Com_do                    | 0     |
| Com_drop_db               | 0     |
| Com_drop_event            | 0     |
| Com_drop_function         | 0     |
| Com_drop_index            | 0     |
| Com_drop_procedure        | 0     |
| Com_drop_server           | 0     |
| Com_drop_table            | 0     |
| Com_drop_trigger          | 0     |
| Com_drop_user             | 0     |
| Com_drop_view             | 0     |
| Com_empty_query           | 0     |
| Com_execute_sql           | 0     |
| Com_flush                 | 0     |
| Com_grant                 | 0     |
| Com_ha_close              | 0     |
| Com_ha_open               | 0     |
| Com_ha_read               | 0     |
| Com_help                  | 0     |
| Com_insert                | 0     |  //顯示插入所執行的次數
| Com_insert_select         | 0     |
| Com_install_plugin        | 0     |
| Com_kill                  | 0     |
| Com_load                  | 0     |
| Com_lock_tables           | 0     |
| Com_optimize              | 0     |
| Com_preload_keys          | 0     |
| Com_prepare_sql           | 0     |
| Com_purge                 | 0     |
| Com_purge_before_date     | 0     |
| Com_release_savepoint     | 0     |
| Com_rename_table          | 0     |
| Com_rename_user           | 0     |
| Com_repair                | 0     |
| Com_replace               | 0     |
| Com_replace_select        | 0     |
| Com_reset                 | 0     |
| Com_resignal              | 0     |
| Com_revoke                | 0     |
| Com_revoke_all            | 0     |
| Com_rollback              | 0     |
| Com_rollback_to_savepoint | 0     |
| Com_savepoint             | 0     |
| Com_select                | 1     | //顯示查詢所執行的次數
| Com_set_option            | 0     |
| Com_signal                | 0     |
| Com_show_authors          | 0     |
| Com_show_binlog_events    | 0     |
| Com_show_binlogs          | 0     |
| Com_show_charsets         | 0     |
| Com_show_collations       | 0     |
| Com_show_contributors     | 0     |
| Com_show_create_db        | 0     |
| Com_show_create_event     | 0     |
| Com_show_create_func      | 0     |
| Com_show_create_proc      | 0     |
| Com_show_create_table     | 0     |
| Com_show_create_trigger   | 0     |
| Com_show_databases        | 0     |
| Com_show_engine_logs      | 0     |
| Com_show_engine_mutex     | 0     |
| Com_show_engine_status    | 0     |
| Com_show_events           | 0     |
| Com_show_errors           | 0     |
| Com_show_fields           | 0     |
| Com_show_function_status  | 0     |
| Com_show_grants           | 0     |
| Com_show_keys             | 0     |
| Com_show_master_status    | 0     |
| Com_show_open_tables      | 0     |
| Com_show_plugins          | 0     |
| Com_show_privileges       | 0     |
| Com_show_procedure_status | 0     |
| Com_show_processlist      | 0     |
| Com_show_profile          | 0     |
| Com_show_profiles         | 0     |
| Com_show_relaylog_events  | 0     |
| Com_show_slave_hosts      | 0     |
| Com_show_slave_status     | 0     |
| Com_show_status           | 1     |
| Com_show_storage_engines  | 0     |
| Com_show_table_status     | 0     |
| Com_show_tables           | 0     |
| Com_show_triggers         | 0     |
| Com_show_variables        | 0     |
| Com_show_warnings         | 0     |
| Com_slave_start           | 0     |
| Com_slave_stop            | 0     |
| Com_stmt_close            | 0     |
| Com_stmt_execute          | 0     |
| Com_stmt_fetch            | 0     |
| Com_stmt_prepare          | 0     |
| Com_stmt_reprepare        | 0     |
| Com_stmt_reset            | 0     |
| Com_stmt_send_long_data   | 0     |
| Com_truncate              | 0     |
| Com_uninstall_plugin      | 0     |
| Com_unlock_tables         | 0     |
| Com_update                | 0     |   //顯示更新所執行的次數
| Com_update_multi          | 0     |
| Com_xa_commit             | 0     |
| Com_xa_end                | 0     |
| Com_xa_prepare            | 0     |
| Com_xa_recover            | 0     |
| Com_xa_rollback           | 0     |
| Com_xa_start              | 0     |
| Compression               | OFF   |
+---------------------------+-------+
140 rows in set (0.00 sec)

這裏寫圖片描述

還有幾個常用的命令

show status like 'Connections';  //鏈接mysql數據庫的次數
show status like Uptime;  //服務器工作的時間(單位秒)
show status like Slow_queries;  //慢查詢的次數(默認爲10)

2.定位慢查詢

  • 默認情況下mysql不記錄慢查詢日誌,要在啓動的時候指定bin\mysqld.exe,slow-query-log
  • 通過慢查詢日誌定位執行效率較低的sql語句。慢查詢日誌記錄了所有查詢時間超過long_query_time的sql 語句,show variables like 'long_query_time'; set long_query_time=時間;//設置慢查詢時間
  • 查看慢查詢日誌:默認爲數據目錄data中的host-name-slow.log。低版本的mysql需要通過在開啓mysql時使用- -log-slow-queries[=file_name]來配置

3.explain分析問題

執行explain select * from emp where empno=10000;
這裏寫圖片描述

select_type //表示查詢的類型
table       //輸出結果及集的表
type        //表示表的連接類型
possible_keys   //表示查詢時可能用到的索引
key             //表示實際使用的索引
key_len         //索引字段的長度
rows            //掃描的行數
Extra           //執行情況的描述和說明

(三)建立適當的索引

    建立索引可以極大地提高查詢速度,但是查詢速度的提高是以降低插入、更新、刪除的速度爲代價的,這些操作增加了大量的I/0以及增加了磁盤的佔用。

1.索引的類型

  • 主索引:主鍵自動地爲主索引(PRIMARY)
  • 唯一索引(UNIQUE)
  • 普通索引(INDEX)
  • 全文索引(FULLTEXT),只有MYISAM存儲引擎支持,國內全文索引通常使用sphix

2.哪些列上適合添加索引

  • 較爲頻繁的作爲查詢條件的字段應該創建索引
  • 唯一性太差的字段不適合單獨創建索引
  • 更新非常頻繁的字段不適合創建索引
  • 不會出現在WHERE子句中字段不該創建索引
  • 對於創建的多列索引,只要查詢條件是用了最左邊的列,索引一般就會被使用
  • 對於使用like的查詢,查詢如果是’%aaa’,不會使用到索引;如果是’aaa%’會使用到索引
  • 如果條件中有or,即使其中有條件帶索引,也不會使用
  • 如果列類型是字符串, 那一定要在條件中將數據使用引號引起來,否則不適用索引
  • 如果條件中有or,即使其中有條件帶索引,也不會使用
  • 如果使用全表掃描比使用索引快,則不適用索引
    3.索引的使用

  • 創建索引

create [unique|fulltext]  index index_name on tbl_name (col_name [(length)] [asc | desc] , …..);
alter table table_name ADD INDEX [index_name] (index_col_name,...)
添加主鍵(索引) alter table tbl_name ADD primary key(列名,..); 聯合主鍵
  • 刪除索引
drop index index_name on tbl_name;
alter table table_name drop index index_name;
刪除主鍵(索引)比較特別: alter table t_b drop primary key;
  • 查詢索引
 show index from table_name;
 show keys from table_name;
 desc table_Name;

查看索引的使用情況

show status like 'Handler_read%';

這裏寫圖片描述

Handler_read_key //這個值越高越好,表示使用索引查詢到的次數
Handler_read_rnd_next //這個值越高說明查詢低效

(四)常用索引優化

1.大批量插入數據
 (1)對於MyISAM:
alter table table_name disable keys;loading data;alter table table_name enable keys;
(2)對於Innodb
將要導入的數據按照主鍵排序
set unique_checks=0,關閉唯一性校驗。
set autocommit=0,關閉自動提交。
 2.優化group by語句
 默認情況,MySQL對所有的group by col1,col2進行排序。這與在查詢中指定order by col1, col2類似。如果查詢中包括group by但用戶想要避免排序結果的消耗,則可以使用order by null禁止排序
3.有些情況下,可以使用連接來替代子查詢。因爲使用join,MySQL不需要在內存中創建臨時表。
4.如果想要在含有or的查詢語句中利用索引,則or之間的每個條件列都必須用到索引,如果沒有索引,則應該考慮增加索引

(五)選擇合適的存儲引擎

MyISAM:默認的MySQL存儲引擎。如果應用是以讀操作和插入操作爲主,只有很少的更新和刪除操作,並且對事務的完整性、併發性要求不是很高。其優勢是訪問的速度快。在插入數據時,默認放在最後. ,刪除數據後,空間不回收.(不支持事務和外鍵)
InnoDB:提供了具有提交、回滾和崩潰恢復能力的事務安全。但是對比MyISAM,寫的處理效率差一些並且會佔用更多的磁盤空間.支持事務和外鍵

(五)選擇合適的數據類型

1.在精度要求高的應用中,建議使用定點數來存儲數值,以保證結果的準確性。
2.對於存儲引擎是MyISAM的數據庫,如果經常做刪除和修改記錄的操作,要定時執行optimize table table_name;功能對錶進行碎片整理。
3.日期類型要根據實際需要選擇能夠滿足應用的最小存儲的早期類型
create table bbs(id int ,con varchar(1024) , pub_time int);
date(‘Ymd’,時間-3*24*60*60); 2038年-1-19

(六)分表

1.水平分表

查詢電話費,近三個月的數據放入一張表,一年內的放入到另一張表、

2.垂直分表
附:測試腳本

#創建表DEPT



CREATE TABLE dept( /*部門表*/
deptno MEDIUMINT   UNSIGNED  NOT NULL  DEFAULT 0,
dname VARCHAR(20)  NOT NULL  DEFAULT "",
loc VARCHAR(13) NOT NULL DEFAULT ""
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ;



#創建表EMP僱員
CREATE TABLE emp
(empno  MEDIUMINT UNSIGNED  NOT NULL  DEFAULT 0,
ename VARCHAR(20) NOT NULL DEFAULT "",
job VARCHAR(9) NOT NULL DEFAULT "",
mgr MEDIUMINT UNSIGNED NOT NULL DEFAULT 0,
hiredate DATE NOT NULL,
sal DECIMAL(7,2)  NOT NULL,
comm DECIMAL(7,2) NOT NULL,
deptno MEDIUMINT UNSIGNED NOT NULL DEFAULT 0
)ENGINE=MyISAM DEFAULT CHARSET=utf8 ;

#工資級別表
CREATE TABLE salgrade
(
grade MEDIUMINT UNSIGNED NOT NULL DEFAULT 0,
losal DECIMAL(17,2)  NOT NULL,
hisal DECIMAL(17,2)  NOT NULL
)ENGINE=MyISAM DEFAULT CHARSET=utf8;

INSERT INTO salgrade VALUES (1,700,1200);
INSERT INTO salgrade VALUES (2,1201,1400);
INSERT INTO salgrade VALUES (3,1401,2000);
INSERT INTO salgrade VALUES (4,2001,3000);
INSERT INTO salgrade VALUES (5,3001,9999);

# 隨機產生字符串
#定義一個新的命令結束符合
delimiter $$
#刪除自定的函數
drop  function rand_string $$

#這裏我創建了一個函數. 

create function rand_string(n INT)
returns varchar(255)
begin 
 declare chars_str varchar(100) default
   'abcdefghijklmnopqrstuvwxyzABCDEFJHIJKLMNOPQRSTUVWXYZ';
 declare return_str varchar(255) default '';
 declare i int default 0;
 while i < n do 
   set return_str =concat(return_str,substring(chars_str,floor(1+rand()*52),1));
   set i = i + 1;
   end while;
  return return_str;
  end $$


delimiter ;
select rand_string(6);

# 隨機產生部門編號
delimiter $$
drop  function rand_num $$

#這裏我們又自定了一個函數
create function rand_num( )
returns int(5)
begin 
 declare i int default 0;
 set i = floor(10+rand()*500);
return i;
  end $$


delimiter ;
select rand_num();

#******************************************
#向emp表中插入記錄(海量的數據)


delimiter $$
drop procedure insert_emp $$



create procedure insert_emp(in start int(10),in max_num int(10))
begin
declare i int default 0; 
 set autocommit = 0;  
 repeat
 set i = i + 1;
 insert into emp values ((start+i) ,rand_string(6),'SALESMAN',0001,curdate(),2000,400,rand_num());
  until i = max_num
 end repeat;
   commit;
 end $$


delimiter ;
#調用剛剛寫好的函數, 1800000條記錄,從100001號開始
call insert_emp(100001,1800000);


#**************************************************************
#  向dept表中插入記錄

delimiter $$
drop procedure insert_dept $$


create procedure insert_dept(in start int(10),in max_num int(10))
begin
declare i int default 0; 
 set autocommit = 0;  
 repeat
 set i = i + 1;
 insert into dept values ((start+i) ,rand_string(10),rand_string(8));
  until i = max_num
 end repeat;
   commit;
 end $$


delimiter ;
call insert_dept(100,10);





#------------------------------------------------
#向salgrade 表插入數據
delimiter $$
drop procedure insert_salgrade $$
create procedure insert_salgrade(in start int(10),in max_num int(10))
begin
declare i int default 0; 
 set autocommit = 0;
 ALTER TABLE emp DISABLE KEYS;  
 repeat
 set i = i + 1;
 insert into salgrade values ((start+i) ,(start+i),(start+i));
  until i = max_num
 end repeat;
   commit;
 end $$
delimiter ;
#測試不需要了
#call insert_salgrade(10000,1000000);
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章