SQL提示(SQL HINT)是優化數據庫的一種重要手段,簡單來講就是在SQL語句中加入一些人爲的提示來達到優化操做的目的。mysql
下面是一個使用SQL提示的例子:sql
SELECT SQL_BUFFER_RESULTS * FROM ……
這個語句將強制MySQL 生成一個臨時結果集。只要臨時結果集生成後,全部表上的鎖定均被釋放。這能在遇到鎖問題時或者更長時間將結果傳給客戶端時有所幫助,由於能夠儘快釋放鎖資源。數據庫
下面是一些在MySQL中經常使用的SQL提示。學習
USE INDEX優化
在查詢語句中表名的後面,添加USE INDEX 來提供但願MySQL 去參考的索引列表,就能夠讓MySQL 不在考慮其餘可用的索引。code
mysql> show index from rental; +--------+------------+---------------------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ | Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | +--------+------------+---------------------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ | rental | 0 | PRIMARY | 1 | rental_id | A | 16008 | NULL | NULL | | BTREE | | | | rental | 0 | rental_date | 1 | rental_date | A | 16008 | NULL | NULL | | BTREE | | | | rental | 0 | rental_date | 2 | inventory_id | A | 16008 | NULL | NULL | | BTREE | | | | rental | 0 | rental_date | 3 | customer_id | A | 16008 | NULL | NULL | | BTREE | | | | rental | 1 | idx_fk_inventory_id | 1 | inventory_id | A | 16008 | NULL | NULL | | BTREE | | | | rental | 1 | idx_fk_customer_id | 1 | customer_id | A | 1231 | NULL | NULL | | BTREE | | | | rental | 1 | idx_fk_staff_id | 1 | staff_id | A | 4 | NULL | NULL | | BTREE | | | +--------+------------+---------------------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ 7 rows in set (0.00 sec) mysql> mysql> explain select count(*) from rental use index(rental_date); +----+-------------+--------+-------+---------------+-------------+---------+------+-------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+--------+-------+---------------+-------------+---------+------+-------+-------------+ | 1 | SIMPLE | rental | index | NULL | rental_date | 10 | NULL | 16008 | Using index | +----+-------------+--------+-------+---------------+-------------+---------+------+-------+-------------+ 1 row in set (0.00 sec)
2. IGNORE INDEX 索引
若是用戶只是單獨地想讓MySQL忽略一個或者多個索引,則能夠用IGNORE INDEX 做爲 HINT。
資源
mysql> explain select count(*) from rental; +----+-------------+--------+-------+---------------+-----------------+---------+------+-------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+--------+-------+---------------+-----------------+---------+------+-------+-------------+ | 1 | SIMPLE | rental | index | NULL | idx_fk_staff_id | 1 | NULL | 16008 | Using index | +----+-------------+--------+-------+---------------+-----------------+---------+------+-------+-------------+ 1 row in set (0.00 sec) mysql> explain select count(*) from rental ignore index (idx_fk_staff_id); +----+-------------+--------+-------+---------------+--------------------+---------+------+-------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+--------+-------+---------------+--------------------+---------+------+-------+-------------+ | 1 | SIMPLE | rental | index | NULL | idx_fk_customer_id | 2 | NULL | 16008 | Using index | +----+-------------+--------+-------+---------------+--------------------+---------+------+-------+-------------+ 1 row in set (0.00 sec)
從執行計劃能夠看出,系統忽略了指定的索引idx_fk_staff_id, 使用索引idx_fk_customer_idit
3. FORCE INDEXio
爲強制MySQL 使用一個特定的索引,可在查詢中使用FORCE INDEX 做爲HINT。
例如,當不強制使用索引的時候,由於大部分庫存inventory_id 的值都是大於1的,所以MySQL會默認使用全表掃描,而 不 使用索引,以下所示:
mysql> explain select * from rental where inventory_id >1\G; *************************** 1. row *************************** id: 1 select_type: SIMPLE table: rental type: ALL possible_keys: idx_fk_inventory_id key: NULL key_len: NULL ref: NULL rows: 16008 Extra: Using where 1 row in set (0.00 sec)
嘗試使用use index 的hint 看看:
mysql> explain select * from rental use index(idx_fk_inventory_id) where inventory_id >1\G; *************************** 1. row *************************** id: 1 select_type: SIMPLE table: rental type: ALL possible_keys: idx_fk_inventory_id key: NULL key_len: NULL ref: NULL rows: 16008 Extra: Using where 1 row in set (0.00 sec)
發現仍然不行,MySQL仍是選擇走全表掃描。可是,當使用FORCE INDEX進行提示時,即便使用索引的效率不是很高,MySQL 仍是選擇使用索引,這是MySQL留給用戶的一個自行選擇執行計劃的權利。
加入FORCE INDEX 提示後再次執行上面的SQL:
mysql> explain select * from rental force index(idx_fk_inventory_id) where inventory_id >1\G; *************************** 1. row *************************** id: 1 select_type: SIMPLE table: rental type: range possible_keys: idx_fk_inventory_id key: idx_fk_inventory_id key_len: 3 ref: NULL rows: 8004 Extra: Using index condition 1 row in set (0.00 sec)
學習自《深刻淺出mysql》