18. SQL優化
1 優化SQL語句的一般步驟
1.1 通過 show status命令瞭解各種SQL的執行頻率
MySQL客戶端連線成功後,通過show[session|global]status
命令可以提供伺服器狀態資訊
# 所有儲存引擎的表統計資訊 show status like 'Com_%'; # InnoDB相關的表統計資訊 show status like 'Innodb_%'; # 檢視資料庫基本情況 # Connections:試圖連線 MySQL 伺服器的次數。 # Uptime:伺服器工作時間。 # Slow_queries:慢查詢的次數。 show status like 'Connections|Uptime|Slow_queries';
Com_xxx 表示每個 xxx 語句執行的次數,我們通常比較關心的是以下幾個統計引數。
- Com_select:執行 select 操作的次數,一次查詢只累加 1。
- Com_insert:執行 INSERT 操作的次數,對於批量插入的 INSERT 操作,只累加一次。
- Com_update:執行 UPDATE 操作的次數。
- Com_delete:執行 DELETE 操作的次數。
1.2 定位執行效率低的SQL語句
1.3 通過EXPLAIN分析低效率SQL的執行計劃
通過 EXPLAIN 或者 DESC 命令獲取 MySQL如何執行 SELECT 語句的資訊,包括在 SELECT 語句執行過程中表如何連線和連線的順序。
1.4 確定問題並採取相應的優化措施
如果經過上述步驟已經分析出問題出現的原因,此時使用者可以根據情況進行相應的優化。
比如全表掃描導致查詢效率低可以考慮新增索引。
2 索引問題
2.1 索引的儲存分類
MyISAM 儲存引擎的表的資料和索引是自動分開儲存的,各自是獨立的一個檔案;InnoDB儲存引擎的表的資料和索引是儲存在同一個表空間裡面,但可以有多個檔案組成。
MySQL 中索引的儲存型別目前只有兩種(BTREE 和 HASH),具體和表的儲存引擎相關:MyISAM 和 InnoDB 儲存引擎都只支援 BTREE 索引;MEMORY/HEAP 儲存引擎可以支援 HASH和 BTREE 索引
2.2 MySQL如何使用索引
1、使用索引
(1)多列索引,最左原則,查詢的條件中用到了最左邊的列,索引一般就會使用。
(2)like查詢,後面如果是常量並且只有%號不在第一個字元,索引才可能被使用。
(3)如果對大的文字進行搜尋,使用全文索引而不用使用 like ‘%…%’。
2、存在索引但不使用索引
(1)如果 MySQL 估計使用索引比全表掃描更慢,則不使用索引。例如如果列key_part1 均勻分佈在 1 和 100 之間,下列查詢中使用索引就不是很好:
SELECT * FROM table_name where key_part1 > 1 and key_part1 < 90;
(2)or分割開的條件,如果or前的條件的列中有索引,而後面的列中沒有索引,那麼涉及到的索引都不會被用到。
(3)like後面的值以%開頭
(4)如果列型別是字串,那麼一定記得在 where 條件中把字元常量值用引號引起來,否則的話即便這個列上有索引,MySQL 也不會用到的。
2.3 檢視索引使用情況
如果索引正在工作,Handler_read_key 的值將很高,這個值代表了一個行被索引值讀的次數,很低的值表明增加索引得到的效能改善不高,因為索引並不經常使用。 Handler_read_rnd_next 的值高則意味著查詢執行低效,並且應該建立索引補救。這個值的含義是在資料檔案中讀下一行的請求數。如果正進行大量的表掃描,Handler_read_rnd_next
的值較高,則通常說明表索引不正確或寫入的查詢沒有利用索引,具體如下。
mysql> show status like 'Handler_read%';
+-----------------------+-------+
| Variable_name | Value |
+-----------------------+-------+
| Handler_read_first | 0 |
| Handler_read_key | 5 |
| Handler_read_next | 0 |
| Handler_read_prev | 0 |
| Handler_read_rnd | 0 |
| Handler_read_rnd_next | 2055 |
+-----------------------+-------+
3 兩個簡單實用的優化方法
3.1 定期分析表和檢查表
analyze table tb1_name[,tb2_name]...
check table tb_name...;
3.2 定期優化表
優化表的語法如下:
OPTIMIZE [LOCAL | NO_WRITE_TO_BINLOG] TABLE tbl_name [, tbl_name] ...
如果已經刪除了表的一大部分,或者如果已經對含有可變長度行的表(含有 VARCHAR、BLOB 或 TEXT 列的表)進行了很多更改,則應使用 OPTIMIZE TABLE 命令來進行表優化。這個命令可以將表中的空間碎片進行合併,並且可以消除由於刪除或者更新造成的空間浪費,但OPTIMIZE TABLE 命令只對 MyISAM、BDB 和 InnoDB 表起作用。
ANALYZE、CHECK、OPTIMIZE 執行期間將對錶進行鎖定,因此一定注意要在資料庫不繁忙的時候執行相關的操作。
4 常用SQL的優化
搜尋資料瞭解,
USE INDEX(index_name...);
IGGNORE INDEX(index_name...);
FORCE INDEX(index_name...);