MySQL 優化系列 --3.SQL語句優化

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;                 // 表連接不會有索引失效問題 (如果索引創建正確的話)







 



















     













     





發佈了60 篇原創文章 · 獲贊 114 · 訪問量 47萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章