3.1 SQL語句的一般優化步驟
session :(默認的)表示當前連接
global: 表示自數據庫啓動至今.
-1. show status ; //用於瞭解SQL語句的執行頻率,重點跟蹤以com開頭的命令.
-2. show status like "com_insert %" //顯示執行插入語句的次數.(批量操作只算 1 條執行語句).
-3. show status like "com_select%" //顯示執行查詢語句的次數.
-4 show status like "com_update%" //顯示執行更新語句的次數
-5 show status like "com_delete%" //顯示執行刪除語句的次數.
只針對inndb存儲引擎的
-1. show status like "innodb_rows_read"; //顯示執行查詢語句的次數.
-2. show status like "innodb_rows_inserted"; //顯示執行插入語句的次數.
-3. show status like "innodb_rows_updated" //顯示執行更新語句的次數.
-4. show status like "innodb_rows_deleted" //顯示執行刪除語句的次數.
-5. show status like "%connections%"; //顯示 MySQL的數量;
-6. show status like "%uptime%" //顯示服務器工作的時間(以秒爲單位)
-7. show status like "%slow_queries%" //顯示慢查詢的次數.
-8. show variable like "%quer%"; //顯示慢查詢是否被開啓.
-8: //顯示: log_slow_queries off //慢查詢日誌沒有開啓
-9. show variable like "%connection%" //顯示MySQL服務器的連接數.
-9. //顯示: max_connections 100 //最大連接數
10. show status like"%conn%"; //顯示MySQL服務器的連接數.
10. //顯示: Connection 3 //試圖連接到(不管是否成功)MySQL服務器的連接數
10. //顯示: Max_used_connections 3 //服務器啓動後已經同時使用的連接的最大數量
10. //顯示: Threads_connected 3 //當前的連接數
開啓慢查詢日誌: ( http://www.cnblogs.com/gzgccsu/archive/2013/01/23/2873598.html 這裏有講開啓慢查詢日誌 )
-1. Linux下
找到mysql的配置文件my.ini, 在mysqld下方加入慢查詢的配置語句(注意:一定要在[mysqld]下的下方加入)
log-slow-queries = /var/lib/mysql/mysql-slow.log
long_query_time = 10
-2. Windows下
log-slow-queries = C:/Program Files/MySQL/MySQL Server 5.5/log/mysql-slow.log" // windows下一定要寫絕對路徑.
long_query_time = 10 // 最長執行時間,可根據實際情況更改.
慢查詢:默認是關閉的. 開啓慢查詢後,一條語句執行時間超過10秒就會被記錄.
3.1.2 定位執行效率低的語句的步驟;
-1. 查慢查詢日誌.
-2. 查異常語句影響行數.
-3. 檢查是否使用索引或者索引是否被執行.
-4. desc ... 語句執行後檢查是否優化.(主要是圍繞索引優化)
desc select * from t1 where id=1 \G // 注意不加 ; 號
mysql> desc select * from t1 where id=1 \G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: t1
type: const
possible_keys: PRIMARY
key: PRIMARY
key_len: 4
ref: const
rows: 1
Extra:
1 row in set (0.00 sec)
-1. rows 1 // 影響行數,掃描行的數量
-2. select_type SIMPLE // simple 表示不使用表連接或子查詢, primary 主查詢(外層查詢), union(union中的第二個查詢),
subqurty子查詢的第一個select.
-3. table t1 // 輸出結果集的表
-4. possible_keys: PRIMARY // 可能用到的suoyin
-5. key: PRIMARY // 實際使用的索引
-6. type: const // 表的連接類型, system (表僅一行), const(只一行匹配), eq_ref(對於前面的每一行使用主鍵和唯一索引)
ref(沒有使用主鍵和唯一索引), range(範圍查詢), index_merge(索引合併優化),
unique_subquery(主鍵子查詢), index_subquery(非主鍵子查詢)
index(通過查詢索引得到數據), all(通過全表掃描得到數據.應該避免全表掃描.)
// 注意: 一般問題多在order by .. group by.. Where.. 等條件語句後沒有加索引或索引失效引起的查詢慢.
-7. ref: // 推薦使用的索引類型
-8. Extra:Using where; Using index // 使用過where , 使用過索引
3.2 索引問題
3.2.1 索引的存儲分類
-1. myisam存儲引擎的表的數據和索引是自動分來存儲的,各自是獨立的一個文件.
-2. innodb存儲引擎的表的數據和索引是存儲在同一個表的空間裏面,但是可以有多個文件組成.
-3. MySQL暫時不支持函數索引.
// 注意: 索引一般加在條件語句後如where... having... group by... order by... 或者頻繁使用的語句.
3.2.2 使用索引
-1 如何使用索引
-1.1. 對於創建的多列索引,只要查詢的條件中用到最左邊的列,索引一般就會被使用.
show index from t1 //查詢t1表的索引
drop index inx_name on t1; //刪除t1表的名爲inx_name的索引.
select * from t1 where name="user0"; //查詢name是user0的列
create index inx_sum on t1(name,salary); //給name列和salary列添加聯合索引
desc select * from t1 where name="user0") \G //顯示 索引被使用, rows只查了1行. 所以只要查詢的條件中用到最左邊的列,索引一般就會被使用.
desc select * from t1 where salary=101 \G //顯示沒有使用索引.rows查詢了10行. 查詢聯合索引的右側的列,索引沒有被使用.
-1.2. 使用 like 查詢 如果%不是第一個字符,可以使用索引,否則索引失效.
drop index inx_sum on t1 ; //刪除t1表的名字是inx_sum的索引
create index inx_name on t1(name) ; //給t1表name列創建名爲inx_name的索引.
desc select * from t1 where name like "%ser%" \G //顯示 rows查詢了所有列. 索引失效.
desc select * from t1 where name like "user5%" \G //顯示 rows查詢了2行,索引可以用.
-1.3. 列名是索引,使用column_name is null 將使用索引.
-2 存在索引,但不使用索引的情況
-2.1. 如果SQL計算使用索引比全表掃描時間長,將放棄使用索引.
-2.2. 用or分割開的語句,如果or左側使用索引,右側沒有使用索引,那麼將都不使用索引.
-2.3. 如果表使用了聯合索引(2個列一起被創建爲索引) 只有 create index inx_sum on t1(name,salary); 的name列可以使用索引.salary列將不使用索引.
-2.4 like 是以%開頭的,將不使用索引. 如 select * from t1 where name like" user5%" \G //將使用索引.
-2.5 如果列類型是字符串,查詢時候使用了 int型.也將不會使用索引
desc select * from t2 where name = 1 \G //將不會使用索引
show atatus like "handler_read%";
// 顯示: handler_read_key值很高,說明索引實用正常.
// 顯示: handler_read_rnd_next 值涵高, 就說明需要檢查索引是否存在或者有效.
3.3 實用的表優化
3.3.1 定期分析表和檢查表
analyze table sales; //用於分析和存儲表的關鍵字分佈,
check table table_name // 用於檢查表是否正常可用.
3.3.3 定期表優化
如果有頻繁刪除表或者修改表字段長度.需要定期做優化.合併空間碎片.
optimize table table_name //優化表空間,提取碎片和空洞. 注意只針對myisam, bdb, innodb表引擎有效.
3.4 常用SQL優化
3.4.1 大批量導入導出數據
myisam引擎使用load命令時候可以配合使用:
alter table t1 disable keys; //關閉使用t1表的索引. 在myisam引擎下會提高導出速度.
alter table t1 enable keys; //恢復使用t1表的索引.
注意: 唯一索引不建議關閉.
-1. innodb引擎表的主鍵是順序保存的,將導出數據的主鍵,順序排列用可以提高導入數據的效率. (linux下的命令語句)
load data infile"/test.txt" into t1(name); //給t1表的name列快速導入數據.
select name from t1 into outfile"/test.txt"; //導出t1表的name列數據快速導出到test.txt文件中.(適合新手,大神,請收下膝蓋)
-2. 關閉唯一性校檢可以提高效率.
在導入數據前先執行 set unique_checks=0; //關閉唯一性校檢. 導入數據結束後在恢復唯一性校檢. set unique_checks=1;
--- 如果確定關閉唯一索引不會引起問題, 關閉唯一索引在導入數據也會提高效率.
-3. 關閉自動提交可以提高導入速度.
在導入數據前先關閉自動提交,也可以提高導入速度. set autcommit=0; //關閉自動提交事務. set autocomit=1; //打開自動提交.
3.4.2 優化insert 語句
insert into t1(name) values ("user1"), ("user2"), ("user3"); //一次插入多值,減少表連接次數.也可以提高效率.
3.4.3 優化group by 語句
分組語句默認帶升序排序.可以使用 order by null 來禁止其排序來提高效率.
select * from t1 where group by name order by null;
3.4.5 優化嵌套排序
嵌套查詢效率沒有表連接效率高. 建議使用表連接來代替嵌套查詢.
當使用嵌套查詢時: 如果內外側查詢都使用了索引, 就只有內側查詢索引有效. 外層查詢索引沒用.
select * from t1 where id in(select id from t2); //外層select查詢索引沒有用.只有內層查詢索引有效.
等價於
select t1.* from t1, t2 where t1.id = t2.id; // 表連接不會有索引失效問題 (如果索引創建正確的話)