Innodb 存储引擎 学习笔记 -索引(一)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_32095699/article/details/88418774

索引管理

先创建一张表:index_

mysql> create table index_(
    -> id int auto_increment,
    -> score int not null,
    -> primary key (id)
    -> );
Query OK, 0 rows affected (0.09 sec)

1.添加索引

给score添加索引s_idx:

mysql> alter table index_
    -> add key s_idx(score);
Query OK, 0 rows affected (0.08 sec)
Records: 0  Duplicates: 0  Warnings: 0

2.查看索引

mysql> show index from index_;
+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| Table  | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| index_ |          0 | PRIMARY  |            1 | id          | A         |           0 |     NULL |   NULL |      | BTREE      |         |               | YES     | NULL       |
| index_ |          1 | s_idx    |            1 | score       | A         |           0 |     NULL |   NULL |      | BTREE      |         |               | YES     | NULL       |
+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
2 rows in set (0.07 sec)

每一列的含义:

table

The name of the table

non_unique

1 if the index can contain duplicates, 0 if it can.

key_name

The name of the index. The primary key index always has the name of PRIMARY.

seq_in_index

The column sequence number in the index. The first column sequence number starts from 1.

column_name

The column name

collation

Collation represents how the column is sorted in the index. A means ascending, B means descending, or NULL means not sorted.

cardinality

The cardinality returns an estimated number of unique values in the index.

Note that the higher the cardinality, the greater the chance that the query optimizer uses the index for lookups.

sub_part

The index prefix. It is null if the entire column is indexed. Otherwise, it shows the number of indexed characters in case column is partially indexed.

packed

indicates how the key is packed; NUL if it is not.

null

YES if the column may contain NULL values and blank if it does not.

index_type

represents the index method used such as BTREEHASHRTREE, or FULLTEXT.

3.cardinality值讲解

cardinality表示一个字段中,不同的值有多少个,它是Innodb选择索引的一个重要标志。

建立索引的前提是,列中的数据是高选择性的,即这个列会都多个不同的值。举个例子:如果我们对性别添加索引,那么可取值的范围只有两个‘male'或’female',这时候添加B+数索引就完全没有必要。但如果某个字段取值很广,几乎没有重复,即属于高选择性,则此时使用B+树索引是最合适的。

现在,我们试着往index_表插入3条数据:

mysql> insert into index_ (score) values (11),(12),(13);
Query OK, 3 rows affected (0.07 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> select * from index_;
+----+-------+
| id | score |
+----+-------+
|  1 |    11 |
|  2 |    12 |
|  3 |    13 |
+----+-------+
3 rows in set (0.00 sec)

不同的id值有3个,不同的score值有3个,因此id的cardinality为3,score的cardinality也为3。

查看index状态:

mysql> show index from index_;
+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| Table  | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| index_ |          0 | PRIMARY  |            1 | id          | A         |           0 |     NULL |   NULL |      | BTREE      |         |               | YES     | NULL       |
| index_ |          1 | s_idx    |            1 | score       | A         |           0 |     NULL |   NULL |      | BTREE      |         |               | YES     | NULL       |
+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
2 rows in set (0.01 sec)

注意:Cardinality的值是一个估计值,因此表中显示的是0,但很显然Cardinality应该为3。

要得到精确的Cardinality值,我们可以使用analyze table 命令更新索引Cardinality的信息:

mysql> analyze table index_;
+-----------------------+---------+----------+----------+
| Table                 | Op      | Msg_type | Msg_text |
+-----------------------+---------+----------+----------+
| partition_test.index_ | analyze | status   | OK       |
+-----------------------+---------+----------+----------+
1 row in set (0.02 sec)

mysql> show index from index_;
+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| Table  | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| index_ |          0 | PRIMARY  |            1 | id          | A         |           3 |     NULL |   NULL |      | BTREE      |         |               | YES     | NULL       |
| index_ |          1 | s_idx    |            1 | score       | A         |           3 |     NULL |   NULL |      | BTREE      |         |               | YES     | NULL       |
+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
2 rows in set (0.00 sec)

可以看到现在Cardinality=3

Innodb存储引擎是怎么统计Cardinality的呢?

如果一张表有50G数据,那么统计一次Cardinality的时间可能非常长,因此数据库对于Cardinality的统计都采用采样的方法来完成。

什么时候更新Cardinality值?

Innodb内部更新Cardinality的策略为:

1)表中1/16的数据已发生过变化

2)stat_modified_counter>2000 000 000

stat_modified_counter是innodb内的一个计数器,用来统计数据发生变化的次数。如一行数据发生多次变化就不能使用1)的策略来统计了。

怎么更新Cardinality值?

Innodb默认对随机的8个叶子节点进行采样。

采样过程如下:

1)统计B+树索引中叶子节点的数量,记为A.

2)随机取得B+树中8个叶子节点,统计每页中不同记录的个数,即为P1,P2...P8.

3)根据采样信息给出Cardinality的预估值:Cardinality = A*(P1+P2+......+P8)/8 ;

当执行SQL语句 analyze table , show table status , show index时会导致Innodb重新计算索引的Cardinality值。

猜你喜欢

转载自blog.csdn.net/qq_32095699/article/details/88418774