Mysql
為什麼即使強制執行此命令,MySQL 也會忽略索引?
我執行
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 表
這是一個索引列
為什麼我要查看索引時
- 有沒有
WHERE
條款?- 我總是要反彈回到桌子上?
由於 InnoDB 表中的所有行都位於與 gen_clust_index 相同的 16K 塊中,因此我將進行全表掃描。
查詢優化器選擇阻力最小的路徑。
你會感到有點震驚,但它是這樣的:你知道查詢優化器將以完全不同的方式處理 MyISAM 嗎?
你可能會說哈????如何 ????
MyISAM 將數據儲存在
.MYD
文件中,並將所有索引儲存在.MYI
文件中。相同的查詢將產生不同的 EXPLAIN 計劃,因為索引與數據位於不同的文件中。為什麼 ?原因如下:
- 所需數據(
last_name
列)已在.MYI
- 在最壞的情況下,您將進行全索引掃描
- 您只能
last_name
從索引中訪問該列- 你不需要篩選不需要的
- 您不會觸發臨時文件創建以進行排序
怎麼能這麼肯定?我已經測試了關於如何使用不同的儲存將生成不同的 EXPLAIN 計劃(有時是更好的計劃)的工作理論:索引必須覆蓋所有選定的列才能用於 ORDER BY?