Mysql

為什麼即使強制執行此命令,MySQL 也會忽略索引?

  • December 11, 2015

我執行EXPLAIN

mysql> explain select last_name from employees order by last_name;
+----+-------------+-----------+------+---------------+------+---------+------+-------+----------------+  
| id | select_type | table     | type | possible_keys | key  | key_len | ref  | rows  | Extra          |
+----+-------------+-----------+------+---------------+------+---------+------+-------+----------------+  
|  1 | SIMPLE      | employees | ALL  | NULL          | NULL | NULL    | NULL | 10031 | Using filesort |
+----+-------------+-----------+------+---------------+------+---------+------+-------+----------------+  
1 row in set (0.00 sec)  

我表中的索引:

mysql> show index from employees;  
+-----------+------------+---------------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+---------------+  
| Table     | Non_unique | Key_name      | Seq_in_index | Column_name   | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |  
+-----------+------------+---------------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+---------------+  
| employees |          0 | PRIMARY       |            1 | subsidiary_id | A         |           6 |     NULL | NULL   |      | BTREE      |         |               |  
| employees |          0 | PRIMARY       |            2 | employee_id   | A         |       10031 |     NULL | NULL   |      | BTREE      |         |               |  
| employees |          1 | idx_last_name |            1 | last_name     | A         |       10031 |      700 | NULL   |      | BTREE      |         |               |  
| employees |          1 | date_of_birth |            1 | date_of_birth | A         |       10031 |     NULL | NULL   | YES  | BTREE      |         |               |  
| employees |          1 | date_of_birth |            2 | subsidiary_id | A         |       10031 |     NULL | NULL   |      | BTREE      |         |               |  
+-----------+------------+---------------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+---------------+  
5 rows in set (0.02 sec)  

last_name 上有一個索引,但優化器不使用它。

所以我這樣做:

mysql> explain select last_name from employees force index(idx_last_name) order by last_name;  
+----+-------------+-----------+------+---------------+------+---------+------+-------+----------------+  
| id | select_type | table     | type | possible_keys | key  | key_len | ref  | rows  | Extra          |  
+----+-------------+-----------+------+---------------+------+---------+------+-------+----------------+  
|  1 | SIMPLE      | employees | ALL  | NULL          | NULL | NULL    | NULL | 10031 | Using filesort |  
+----+-------------+-----------+------+---------------+------+---------+------+-------+----------------+  
1 row in set (0.00 sec)  

仍然****沒有使用索引!我在這裡做錯了什麼?

這是否與索引為 的事實有關NON_UNIQUE?順便說一句,last_name 是VARCHAR(1000)

@RolandoMySQLDBA 要求更新

mysql> SELECT COUNT(DISTINCT last_name) DistinctCount FROM employees;  
+---------------+  
| DistinctCount |  
+---------------+  
|         10000 |  
+---------------+  
1 row in set (0.05 sec)  


mysql> SELECT COUNT(1) FROM (SELECT COUNT(1) Count500,last_name FROM employees GROUP BY last_name HAVING COUNT(1) > 500) A;  
+----------+  
| COUNT(1) |  
+----------+  
|        0 |  
+----------+  
1 row in set (0.15 sec)  

問題 #1

看查詢

select last_name from employees order by last_name;

我沒有看到有意義的 WHERE 子句,MySQL 查詢優化器也沒有。沒有使用索引的動機。

問題 #2

看查詢

select last_name from employees force index(idx_last_name) order by last_name; 

你給了它一個索引,但是查詢優化器接管了它。我以前見過這種行為(如何強制 JOIN 使用 MySQL 中的特定索引?

為什麼會發生這種情況?

如果沒有WHERE子句,查詢優化器會對自己說以下內容:

  • 這是一個 InnoDB 表

  • 這是一個索引列

  • 該索引具有gen_clust_index(又名聚集索引)的 row_id

  • 為什麼我要查看索引時

    • 有沒有WHERE條款?
    • 我總是要反彈回到桌子上?
  • 由於 InnoDB 表中的所有行都位於與 gen_clust_index 相同的 16K 塊中,因此我將進行全表掃描。

查詢優化器選擇阻力最小的路徑。

你會感到有點震驚,但它是這樣的:你知道查詢優化器將以完全不同的方式處理 MyISAM 嗎?

你可能會說哈????如何 ????

MyISAM 將數據儲存在.MYD文件中,並將所有索引儲存在.MYI文件中。

相同的查詢將產生不同的 EXPLAIN 計劃,因為索引與數據位於不同的文件中。為什麼 ?原因如下:

  • 所需數據(last_name列)已在.MYI
  • 在最壞的情況下,您將進行全索引掃描
  • 您只能last_name從索引中訪問該列
  • 你不需要篩選不需要的
  • 您不會觸發臨時文件創建以進行排序

怎麼能這麼肯定?我已經測試了關於如何使用不同的儲存將生成不同的 EXPLAIN 計劃(有時是更好的計劃)的工作理論:索引必須覆蓋所有選定的列才能用於 ORDER BY?

引用自:https://dba.stackexchange.com/questions/48072