索引實踐和調優(3)

今兒啊,洲際哥給你們帶來兩個8.0的新特性數據庫

Ⅰ、不可見索引

schema_unused_indexes表,這個表有三個列分別是object_schema、object_name、index_name函數

對於這些索引,一般來講,就是刪掉,可是直接刪除有問題啊,可能如今沒用到,過段時間要用啊優化

但在MySQL 8.0中咱們能夠先將索引設置爲invisible,優化器就不會走這個索引,跑一段時間觀察對業務有沒有影響,若是沒有影響再把這個索引刪掉code

(root@localhost) [sys]> select * from schema_unused_indexes limit 3;
+---------------+-------------+---------------------+
| object_schema | object_name | index_name          |
+---------------+-------------+---------------------+
| dbt3          | customer    | i_c_nationkey       |
| dbt3          | lineitem    | i_l_shipdate        |
| dbt3          | lineitem    | i_l_suppkey_partkey |
+---------------+-------------+---------------------+
3 rows in set (0.00 sec)
alter table xxx alter index_name invisible/visible;

Ⅱ、降序索引

(root@localhost) [dbt3]> explain select * from orders where o_custkey = 1 order by o_orderDate,o_orderStatus;
+----+-------------+--------+------------+------+---------------+-------------+---------+-------+------+----------+---------------------------------------+
| id | select_type | table  | partitions | type | possible_keys | key         | key_len | ref   | rows | filtered | Extra                                 |
+----+-------------+--------+------------+------+---------------+-------------+---------+-------+------+----------+---------------------------------------+
|  1 | SIMPLE      | orders | NULL       | ref  | i_o_custkey   | i_o_custkey | 5       | const |    6 |   100.00 | Using index condition; Using filesort |
+----+-------------+--------+------------+------+---------------+-------------+---------+-------+------+----------+---------------------------------------+
1 row in set, 1 warning (0.00 sec)

(root@localhost) [dbt3]> alter table orders add index idx_a_b_c(o_custkey,o_orderDate,o_orderStatus);
Query OK, 0 rows affected (6.33 sec)
Records: 0  Duplicates: 0  Warnings: 0

(root@localhost) [dbt3]> explain select * from orders where o_custkey = 1 order by o_orderDate,o_orderStatus;
+----+-------------+--------+------------+------+-----------------------+-----------+---------+-------+------+----------+-----------------------+
| id | select_type | table  | partitions | type | possible_keys         | key       | key_len | ref   | rows | filtered | Extra                 |
+----+-------------+--------+------------+------+-----------------------+-----------+---------+-------+------+----------+-----------------------+
|  1 | SIMPLE      | orders | NULL       | ref  | i_o_custkey,idx_a_b_c | idx_a_b_c | 5       | const |    6 |   100.00 | Using index condition |
+----+-------------+--------+------------+------+-----------------------+-----------+---------+-------+------+----------+-----------------------+
1 row in set, 1 warning (0.06 sec)

(root@localhost) [dbt3]> explain select * from orders where o_custkey = 1 order by o_orderDate DESC,o_orderStatus;
+----+-------------+--------+------------+------+-----------------------+-------------+---------+-------+------+----------+---------------------------------------+
| id | select_type | table  | partitions | type | possible_keys         | key         | key_len | ref   | rows | filtered | Extra                                 |
+----+-------------+--------+------------+------+-----------------------+-------------+---------+-------+------+----------+---------------------------------------+
|  1 | SIMPLE      | orders | NULL       | ref  | i_o_custkey,idx_a_b_c | i_o_custkey | 5       | const |    6 |   100.00 | Using index condition; Using filesort |
+----+-------------+--------+------------+------+-----------------------+-------------+---------+-------+------+----------+---------------------------------------+
1 row in set, 1 warning (0.00 sec)

綜上所述:到5.7爲止,全部的排序必須是一個方向(A,B,C),由於索引默認都是(A asc,B asc,C asc)這種,若是DESC就得從新排序,即方向不一致就行不通排序

可是線上咱們常常會碰到這種方向不一致的場景,怎麼辦呢?索引

方案一:8.0 新特性ip

alter table orders add index idx_cust_data_status (o_custkey,o_orderDate DESC,o_orderStatus);

其實在5.7中也能夠這樣執行,可是會把desc忽略掉,沒用it

方案二:虛擬列
目前你們基本上還用的5.7,咱們這邊用下面這種函數索引(虛擬列)的方法來實現一下需求io

alter tablename add column as (function(column)) virtual/stored;

virtual 每次訪問這個列須要一次額外計算,不佔任何存儲空間,只是一個計算獲得的列,可是能夠在上面增長一個索引,這個索引是佔空間的,stored 在磁盤上佔據空間table

一般用virtual,不用stored

用函數表達式建立一個虛擬列,datediff是一個日期差,化降序爲升序
(root@localhost) [dbt3]> alter table orders add column o_orderdate2 int as (datediff('2099-01-01',o_orderdate)) virtual;
Query OK, 0 rows affected (0.94 sec)
Records: 0  Duplicates: 0  Warnings: 0

在這個虛擬列上加一個索引
(root@localhost) [dbt3]> alter table orders add index idx_cust_date_status (o_custkey,o_orderdate2,o_orderstatus);
Query OK, 0 rows affected (8.99 sec)
Records: 0  Duplicates: 0  Warnings: 0

(root@localhost) [dbt3]> explain select * from orders where o_custkey = 1 order by o_orderDate2,o_orderStatus;
+----+-------------+--------+------------+------+--------------------------------------------+----------------------+---------+-------+------+----------+-------------+
| id | select_type | table  | partitions | type | possible_keys                              | key                  | key_len | ref   | rows | filtered | Extra       |
+----+-------------+--------+------------+------+--------------------------------------------+----------------------+---------+-------+------+----------+-------------+
|  1 | SIMPLE      | orders | NULL       | ref  | i_o_custkey,idx_a_b_c,idx_cust_date_status | idx_cust_date_status | 5       | const |    6 |   100.00 | Using where |
+----+-------------+--------+------------+------+--------------------------------------------+----------------------+---------+-------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

這個作法只有5.7版本才能用,由於虛擬列和函數索引都是5.7才支持的

Ⅲ、索引傾斜

這個知識點先了解一下便可
背景
訂單status上是否須要建索引,三種狀態 0 1 2

傾斜:大部分狀態是已完成,查詢條件大部分時候是未完成狀態,而這種未完成的狀態又是不多量的,

若是一共1000w,未完成的只有10w,這樣去取是符合B+ tree的條件,從大量數據取小部分數據,這時候自己是有意義的,可是若是去作一些比較複雜的查詢,數據庫的優化器可能會出錯,由於他不知道索引是傾斜的,致使它在選擇上有問題

5.7以前,優化器不能感知索引傾斜,若是優化器的執行計劃出現小誤差,去看下他使用的哪一個索引是否存在傾斜,若是存在那也沒辦法,後面8.0可能會改進

(root@localhost) [dbt3]> explain select * from lineitem where l_orderkey=1;
+----+-------------+----------+------------+------+--------------------------------------------+---------+---------+-------+------+----------+-------+
| id | select_type | table    | partitions | type | possible_keys                              | key     | key_len | ref   | rows | filtered | Extra |
+----+-------------+----------+------------+------+--------------------------------------------+---------+---------+-------+------+----------+-------+
|  1 | SIMPLE      | lineitem | NULL       | ref  | PRIMARY,i_l_orderkey,i_l_orderkey_quantity | PRIMARY | 4       | const |    6 |   100.00 | NULL  |
+----+-------------+----------+------------+------+--------------------------------------------+---------+---------+-------+------+----------+-------+
1 row in set, 1 warning (0.11 sec)
優化器選擇了pk

咱們也能夠強制走索引,但不是很建議這麼作
(root@localhost) [dbt3]> explain select * from lineitem force index(i_l_orderkey) where l_orderkey=1;
+----+-------------+----------+------------+------+---------------+--------------+---------+-------+------+----------+-------+
| id | select_type | table    | partitions | type | possible_keys | key          | key_len | ref   | rows | filtered | Extra |
+----+-------------+----------+------------+------+---------------+--------------+---------+-------+------+----------+-------+
|  1 | SIMPLE      | lineitem | NULL       | ref  | i_l_orderkey  | i_l_orderkey | 4       | const |    6 |   100.00 | NULL  |
+----+-------------+----------+------------+------+---------------+--------------+---------+-------+------+----------+-------+
1 row in set, 1 warning (0.00 sec)
相關文章
相關標籤/搜索