当前位置:网站首页>Research on MySQL composite index

Research on MySQL composite index

2022-06-24 14:06:00 minihuabei

Composite index ( Also known as the union index ), Is an index created on multiple columns . The most important thing to create a composite index is the choice of column order , It's about whether the index can be used , Or how many predicate conditions can be indexed . The use of composite index follows the leftmost matching principle , Only the column to the left of the index matches , The following columns can continue to match . This paper mainly explores the creation order and usage of composite index .

( One ) The concept of composite index

An index created on a single column is called a single column index , stay 2 Indexes created on more than one column are called composite indexes . Creating an index on a single column is relatively easy , Generally, only the selection rate of the column needs to be considered , The more selective , The more scattered the data is , The performance of the index created is better . Usually , The formula for calculating the selection rate of a column is :

selectivity = The number of records returned after the predicate condition is applied / The number of records returned without predicate conditions

The range of optional rate is (0,1], The smaller the value. , The better the selectivity .

For composite indexes ( Also known as the union index ), Is an index created on multiple columns . The most important thing to create a composite index is the choice of column order , It's about whether the index can be used , Or how many predicate conditions can be indexed . The use of composite index follows the leftmost matching principle , Only the column to the left of the index matches , The following columns can continue to match .

( Two ) When will composite index columns be used

Composite indexes follow the leftmost matching principle , Only the leftmost column in the index matches , The next column is likely to be matched . If the left column uses a non equivalent query , The column to the right of the index will not be used by the query , It's not used by sorting .

experiment : In which cases will composite index be used

Which fields in the composite index are used , It's something we're very concerned about . A classic example on the Internet :

--  Create test table 
CREATE TABLE t1(
c1 CHAR(1) not null,
c2 CHAR(1) not null,
c3 CHAR(1) not null,
c4 CHAR(1) not null,
c5 CHAR(1) not null
)ENGINE innodb CHARSET UTF8;
--  Add index 
alter table t1 add index idx_c1234(c1,c2,c3,c4);
-- Insert test data 
insert into t1 values('1','1','1','1','1'),('2','2','2','2','2'),
('3','3','3','3','3'),('4','4','4','4','4'),('5','5','5','5','5');

We need to explore which of the following query statements use the index idx_c1234, And which fields of the index are used ?

(A) where c1=? and c2=? and c4>? and c3=?

(B) where c1=? and c2=? and c4=? order by c3

where c1=? and c4=? group by c3,c2

(D) where c1=? and c5=? order by c2,c3

(E) where c1=? and c2=? and c5=? order by c2,c3

(F) where c1>? and c2=? and c4>? and c3=?

A Options :

mysql> explain select c1,c2,c3,c4,c5 from t1 where c1='2' and c2='2' and c4>'1' and c3='2';
+----+-------------+-------+------------+-------+---------------+-----------+---------+------+------+----------+-----------------------+
| id | select_type | table | partitions | type  | possible_keys | key       | key_len | ref  | rows | filtered | Extra                 |
+----+-------------+-------+------------+-------+---------------+-----------+---------+------+------+----------+-----------------------+
|  1 | SIMPLE      | t1    | NULL       | range | idx_c1234     | idx_c1234 | 12      | NULL |    1 |   100.00 | Using index condition |
+----+-------------+-------+------------+-------+---------------+-----------+---------+------+------+----------+-----------------------+

The index length used is 12, representative 4 All fields are indexed . because c1、c2、c3 They're all equivalent queries , So the back c4 Columns can also be used .

notes :utf8 code , The length of an index is 3, here 12 representative 4 The index is used for all fields .

B Options :

mysql> explain select c1,c2,c3,c4,c5 from t1 where c1='2' and c2='2' and c4='2' order by c3;
+----+-------------+-------+------------+------+---------------+-----------+---------+-------------+------+----------+-----------------------+
| id | select_type | table | partitions | type | possible_keys | key       | key_len | ref         | rows | filtered | Extra                 |
+----+-------------+-------+------------+------+---------------+-----------+---------+-------------+------+----------+-----------------------+
|  1 | SIMPLE      | t1    | NULL       | ref  | idx_c1234     | idx_c1234 | 6       | const,const |    1 |    20.00 | Using index condition |
+----+-------------+-------+------------+------+---------------+-----------+---------+-------------+------+----------+-----------------------+

The index length used is 6, representative 2 Fields use indexes . According to the leftmost usage principle ,c1、c2 Index is used . Because there is no c3 Predicate conditions , So the index value uses c2 And then there was an interruption , The result is that only c1、c2 Column . here SQL Used order by Sort , But in carrying out the plan Extra Some of them have not filesort keyword , Description in index according to c3 Read the data in order .

Pay special attention to , Although in the index c3 The field is not at the end of the index , But it's used in indexes c2 The ordered nature of fields , Because the execution of the plan Extra Some of them didn't appear "fileasort" keyword . Why is that ? It's used here MySQL5.6 Version introduced Index Condition Pushdown (ICP) Optimize . The core idea is to use the fields in the index to do data filtering . Let's sort it out. Don't use it ICP And use ICP The difference between :

If not used ICP Optimize , Its SQL The execution steps are :

1. Use index columns c1,c2 Get the row data that meets the condition .where c1=‘2’ and c2=‘2’

2. Back to the table to query data , Use where c4='2’ To filter the data

3. Sort the data and output

If used ICP Optimize , Its SQL The execution steps are :

1. Use index columns c1,c2 Get the row data that meets the condition .where c1=‘2’ and c2=‘2’

2. Use... In indexes where c4='2’ To filter the data

3. Because the data is in order , Take out the data that meet the conditions directly in order

C Options :

mysql>  explain select c2,c3 from t1 where c1='2' and c4='2' group by c3,c2;
+----+-------------+-------+------------+------+---------------+-----------+---------+-------+------+----------+-----------------------------------------------------------+
| id | select_type | table | partitions | type | possible_keys | key       | key_len | ref   | rows | filtered | Extra                                                     |
+----+-------------+-------+------------+------+---------------+-----------+---------+-------+------+----------+-----------------------------------------------------------+
|  1 | SIMPLE      | t1    | NULL       | ref  | idx_c1234     | idx_c1234 | 3       | const |    2 |    14.29 | Using where; Using index; Using temporary; Using filesort |
+----+-------------+-------+------------+------+---------------+-----------+---------+-------+------+----------+-----------------------------------------------------------+

The index length used is 3, representative 1 Fields use indexes . According to the leftmost usage principle ,c1 Index is used . Because there is no c2 Predicate conditions , So the index value uses c1 And then there was an interruption , The result is that only c1 Column . The SQL The execution process is :

1. stay c1 The column uses the index to find c1='2’ All of the line , Then go back to the table and use c4='2’ Filter out mismatched data

2. According to the last step , On the result of c3,c2 Joint sort , In order to get continuously changing data , At the same time, create temporary tables inside the database , Used to store group by Result .

C Option extension :

mysql> explain select c2,c3 from t1 where c1='2' and c4='2' group by c2,c3;
+----+-------------+-------+------------+------+---------------+-----------+---------+-------+------+----------+--------------------------+
| id | select_type | table | partitions | type | possible_keys | key       | key_len | ref   | rows | filtered | Extra                    |
+----+-------------+-------+------------+------+---------------+-----------+---------+-------+------+----------+--------------------------+
|  1 | SIMPLE      | t1    | NULL       | ref  | idx_c1234     | idx_c1234 | 3       | const |    2 |    14.29 | Using where; Using index |
+----+-------------+-------+------------+------+---------------+-----------+---------+-------+------+----------+--------------------------+

The index length used is 3, representative 1 Fields use indexes . According to the leftmost usage principle ,c1 Index is used .
D Options :

mysql> explain select c2,c3 from t1 where c1='2' and c5='2' order by c2,c3;
+----+-------------+-------+------------+------+---------------+-----------+---------+-------+------+----------+------------------------------------+
| id | select_type | table | partitions | type | possible_keys | key       | key_len | ref   | rows | filtered | Extra                              |
+----+-------------+-------+------------+------+---------------+-----------+---------+-------+------+----------+------------------------------------+
|  1 | SIMPLE      | t1    | NULL       | ref  | idx_c1234     | idx_c1234 | 3       | const |    2 |    14.29 | Using index condition; Using where |
+----+-------------+-------+------------+------+---------------+-----------+---------+-------+------+----------+------------------------------------+

The index length used is 3, representative 1 All fields are indexed . According to the leftmost usage principle ,c1 Index is used . Because there is no c2 Predicate conditions , So the index value uses c1 And then there was an interruption , The result is that only c1 Column .

D Option extension :

mysql> explain select c2,c3 from t1 where c1='2' and c5='2' order by c3,c2;
+----+-------------+-------+------------+------+---------------+-----------+---------+-------+------+----------+----------------------------------------------------+
| id | select_type | table | partitions | type | possible_keys | key       | key_len | ref   | rows | filtered | Extra                                              |
+----+-------------+-------+------------+------+---------------+-----------+---------+-------+------+----------+----------------------------------------------------+
|  1 | SIMPLE      | t1    | NULL       | ref  | idx_c1234     | idx_c1234 | 3       | const |    2 |    14.29 | Using index condition; Using where; Using filesort |
+----+-------------+-------+------------+------+---------------+-----------+---------+-------+------+----------+----------------------------------------------------+

The index length used is 3, representative 1 All fields are indexed . According to the leftmost usage principle ,c1 Index is used . Because there is no c2 Predicate conditions , So the index value uses c1 And then there was an interruption , The result is that only c1 Column .

E Options :

mysql> explain select c1,c2,c3,c4,c5 from t1 where c1='2' and c2='2' and c5='2' order by c2,c3;
+----+-------------+-------+------------+------+---------------+-----------+---------+-------------+------+----------+------------------------------------+
| id | select_type | table | partitions | type | possible_keys | key       | key_len | ref         | rows | filtered | Extra                              |
+----+-------------+-------+------------+------+---------------+-----------+---------+-------------+------+----------+------------------------------------+
|  1 | SIMPLE      | t1    | NULL       | ref  | idx_c1234     | idx_c1234 | 6       | const,const |    2 |    14.29 | Using index condition; Using where |
+----+-------------+-------+------------+------+---------------+-----------+---------+-------------+------+----------+------------------------------------+

The index length used is 6, representative 2 All fields are indexed . According to the leftmost usage principle ,c1、c2 Index is used . here SQL Used order by Sort , But in carrying out the plan Extra Some of them have not filesort keyword , Description in index according to c3 Read the data in order (c2 Is a constant ).

F Options :

mysql> explain select c1,c2,c3,c4,c5 from t1 where c1>'4' and c2='2' and c3='2' and c4='1';
+----+-------------+-------+------------+-------+---------------+-----------+---------+------+------+----------+-----------------------+
| id | select_type | table | partitions | type  | possible_keys | key       | key_len | ref  | rows | filtered | Extra                 |
+----+-------------+-------+------------+-------+---------------+-----------+---------+------+------+----------+-----------------------+
|  1 | SIMPLE      | t1    | NULL       | range | idx_c1234     | idx_c1234 | 3       | NULL |    1 |    20.00 | Using index condition |
+----+-------------+-------+------------+-------+---------------+-----------+---------+------+------+----------+-----------------------+

The index length used is 3, representative 1 All fields are indexed . According to the leftmost usage principle ,c1 Index is used . here c1 Using the unequal value query , Lead to the following c2 Query cannot use index . This case is very alarming , When predicate condition contains equivalence query and range query , If the range query precedes the index , Then the equivalent query will not be able to use the index ; If the equivalent query comes first , The range query is at the end , The index can be used .

( 3、 ... and ) How to create a composite index

The difficulty of creating composite index lies in the selection of field order , My opinion is as follows :

If there is an equivalent query and sort , When creating a composite index , Put the equivalent query field in the front , Sort at the bottom ;
If there are multiple equivalent queries , Put the selective ones in the front , The less selective ones are put in the back ;
If there is an equivalent query 、 Range queries 、 Sort . The equivalent query comes first , Range query and sorting need to determine the index order according to the actual situation ;
Besides ,《 Alibaba Java Development Manual -2020 The latest Songshan Edition 》 There are several conventions about composite index in , We can have a look :

1. If there is order by Scene , Note the use of index order .order by The fields after are part of the composite index , And at the end of the composite index , Avoid filesort The situation of , Affect query performance .

Example :where a=? b=? order by c; Indexes a_b_c

Counter example : Index if there is range query , Then index ordering will not be used . Such as :where a>10 order by b; Indexes a_b Cannot sort .

2. When building a composite index , The highest discrimination is on the left , If where a=? and b=?,a The value of the column is almost unique , So just create a single column index idx_a that will do .

explain : When there are mixed judgment conditions of equal sign and non equal sign , While indexing , Please precede the equal sign condition . Such as :where c>? and d=?, So even c More differentiated , We must also put d At the top of the index , That is to create an index idx_d_c.

experiment : How to create a composite index

In some documents, we have talked about the creation rules of composite index :ESR principle : accurate (Equal) The matching field comes first , Sort (Sort) Conditions in the middle , Range (Range) The matching field is placed at the end . Now let's explore whether this method is correct .

Example : There are employee tables employees

mysql> show create table employees;
+-----------+-------------------------------
| Table     | Create Table                                                                                                                                                                                                                                                                          
+-----------+-------------------------------------
| employees | CREATE TABLE `employees` (
  `emp_no` int(11) NOT NULL,
  `birth_date` date NOT NULL,
  `first_name` varchar(14) NOT NULL,
  `last_name` varchar(16) NOT NULL,
  `gender` enum('M','F') NOT NULL,
  `hire_date` date NOT NULL,
  PRIMARY KEY (`emp_no`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
+-----------+-------------------------------------
--  The amount of data is about 30 Line ten thousand 
mysql> select count(*) from employees;
+----------+
| count(*) |
+----------+
|   300024 |
+----------+

Now we need to check 1998 I'm going to be employed after five years first_name by "Ebbe" staff , And in ascending order by date of birth .

Its SQL The statement is as follows :

select  emp_no,birth_date,first_name,last_name,gender,hire_date 
from    employees 
where   hire_date >= '1998-01-01'
and     first_name = 'Ebbe'
order by birth_date;

To optimize this SQL Statement performance , You need to create an index on the table , In order to ensure where And order by All use indexes , Decided to create a composite index , There is the following order of creation :

(A)hire_date,first_name,birth_date

(B)hire_date,birth_date,first_name

(C)first_name,hire_date,birth_date

(D)first_name,birth_date,hire_date

(E)birth_date,first_name,hire_date

(F)birth_date,hire_date,first_name

Determine which order of index creation is optimal .

Note:

1.date Type account 3 Bytes of space ,hire_date and birth_date All occupied 3 Bytes of space .

2.first_name It's a variable length field , More use 2 Bytes , If allowed NULL value , We need to use more 1 Bytes , Occupy 16 Bytes

A Options :hire_date,first_name,birth_date

create index idx_a on employees(hire_date,first_name,birth_date);

Its implementation plan is as follows :

+----+-------------+-----------+------------+-------+---------------+-------+---------+------+------+----------+---------------------------------------+
| id | select_type | table     | partitions | type  | possible_keys | key   | key_len | ref  | rows | filtered | Extra                                 |
+----+-------------+-----------+------------+-------+---------------+-------+---------+------+------+----------+---------------------------------------+
|  1 | SIMPLE      | employees | NULL       | range | idx_a         | idx_a | 19      | NULL | 5678 |    10.00 | Using index condition; Using filesort |
+----+-------------+-----------+------------+-------+---------------+-------+---------+------+------+----------+---------------------------------------+

here key_len The length is 19, It's puzzling ,hire_date Yes no equivalent query , Theoretically key_len Should be 3, By using MySQL workbench View execution plan , It can also be found that the index only uses hire_date Column ( Here's the picture ). Why would it be 19 instead of 3 Well ? It's really puzzling , After thinking for a long time, I haven't figured it out , If you know , I hope you will give me your answers .
 Insert picture description here

B Options :hire_date,birth_date,first_name

To avoid interference , Delete the index created above idx_a, Then create idx_b.

create index idx_b on employees(hire_date,birth_date,first_name);

Its implementation plan is as follows :

+----+-------------+-----------+------------+-------+---------------+-------+---------+------+------+----------+---------------------------------------+
| id | select_type | table     | partitions | type  | possible_keys | key   | key_len | ref  | rows | filtered | Extra                                 |
+----+-------------+-----------+------------+-------+---------------+-------+---------+------+------+----------+---------------------------------------+
|  1 | SIMPLE      | employees | NULL       | range | idx_b         | idx_b | 3       | NULL | 5682 |    10.00 | Using index condition; Using filesort |
+----+-------------+-----------+------------+-------+---------------+-------+---------+------+------+----------+---------------------------------------+

here key_len The length is 3,hire_date Yes no equivalent query , The following index columns cannot be used .

C Options :first_name,hire_date,birth_date

To avoid interference , Delete the index created above idx_b, Then create idx_c.

create index idx_c on employees(first_name,hire_date,birth_date);

Its implementation plan is as follows :

+----+-------------+-----------+------------+-------+---------------+-------+---------+------+------+----------+---------------------------------------+
| id | select_type | table     | partitions | type  | possible_keys | key   | key_len | ref  | rows | filtered | Extra                                 |
+----+-------------+-----------+------------+-------+---------------+-------+---------+------+------+----------+---------------------------------------+
|  1 | SIMPLE      | employees | NULL       | range | idx_c         | idx_c | 19      | NULL |    5 |   100.00 | Using index condition; Using filesort |
+----+-------------+-----------+------------+-------+---------------+-------+---------+------+------+----------+---------------------------------------+

here key_len The length is 19,first_name It's an equivalent query , Can continue to use hire_date Column , because hire_date Columns are non equivalent queries , The index cannot be used any more birth_date.

D Options :first_name,birth_date,hire_date

To avoid interference , Delete the index created above idx_c, Then create idx_d.

create index idx_d on employees(first_name,birth_date,hire_date);

Its implementation plan is as follows :

+----+-------------+-----------+------------+------+---------------+-------+---------+-------+------+----------+-----------------------+
| id | select_type | table     | partitions | type | possible_keys | key   | key_len | ref   | rows | filtered | Extra                 |
+----+-------------+-----------+------------+------+---------------+-------+---------+-------+------+----------+-----------------------+
|  1 | SIMPLE      | employees | NULL       | ref  | idx_d         | idx_d | 16      | const |  190 |    33.33 | Using index condition |
+----+-------------+-----------+------------+------+---------------+-------+---------+-------+------+----------+-----------------------+

here key_len The length is 16,first_name It's an equivalent query , Not used in predicate filtering birth_date, Lead to only first_name Columns use the upper index , however birth_date Columns are used to sort , The execution plan above shows SQL There's no sort in the end , Explain that the data is from the index according to birth_date It's taken out in order .

E Options :birth_date,first_name,hire_date

To avoid interference , Delete the index created above idx_d, Then create idx_e.

create index idx_e on employees(birth_date,first_name,hire_date);

Its implementation plan is as follows :

+----+-------------+-----------+------------+------+---------------+------+---------+------+--------+----------+-----------------------------+
| id | select_type | table     | partitions | type | possible_keys | key  | key_len | ref  | rows   | filtered | Extra                       |
+----+-------------+-----------+------------+------+---------------+------+---------+------+--------+----------+-----------------------------+
|  1 | SIMPLE      | employees | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 299468 |     3.33 | Using where; Using filesort |
+----+-------------+-----------+------------+------+---------------+------+---------+------+--------+----------+-----------------------------+

The index is not used here , It shows that sorting column placed at the top of composite index cannot be used .

F Options :birth_date,hire_date,first_name

To avoid interference , Delete the index created above idx_e, Then create idx_f.

create index idx_f on employees(birth_date,hire_date,first_name);

Its implementation plan is as follows :

+----+-------------+-----------+------------+------+---------------+------+---------+------+--------+----------+-----------------------------+
| id | select_type | table     | partitions | type | possible_keys | key  | key_len | ref  | rows   | filtered | Extra                       |
+----+-------------+-----------+------------+------+---------------+------+---------+------+--------+----------+-----------------------------+
|  1 | SIMPLE      | employees | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 299468 |     3.33 | Using where; Using filesort |
+----+-------------+-----------+------------+------+---------------+------+---------+------+--------+----------+-----------------------------+

And E Options as , The index is not used here , It shows that sorting column placed at the top of composite index cannot be used .

Through the top 6 An index test , We found that , The equivalent query column and the range query column are placed in front of the composite index , Composite indexes can be used to , It's just that the columns used may be different . Which is the best way to create an index ?MySQL Our query optimizer is based on overhead (cost) To choose the best execution plan , Let's take a look at the above 6 The execution cost of each index .

 Indexes           expenses cost
---------- ------------
idx_a        8518
idx_b        8524
idx_c        13
idx_d        228
idx_e        78083
idx_f        78083

Through the overhead above , You can see :

idx_a and idx_b: The index uses the beginning of the range query field , The index can only be used to the first column , Cannot eliminate sorting , It leads to high cost ;
idx_c and idx_d: The index starts with the equivalent query field , Range queries and sorting come after , The cost is minimal ;
idx_e and idx_f : The index starts with a sort field , The index cannot be used , Full scan of walking , It's expensive .

Further more ,idx_c and idx_d How to choose ?idx_c Using indexes for equivalent queries + Range queries , Then sort the data ;idx_d Using indexes for equivalent queries + Push down query under index condition , Then get the data directly in order . There are advantages and disadvantages in the two ways , Let's take another example :

Top up 6 All indexes are added to the table , Take a look at this SQL Which index will be selected .

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 | emp_no      | A         |      299468 | NULL     | NULL   |      | BTREE      |         |               |
| employees |          1 | idx_a    |            1 | hire_date   | A         |        5355 | NULL     | NULL   |      | BTREE      |         |               |
| employees |          1 | idx_a    |            2 | first_name  | A         |      290745 | NULL     | NULL   |      | BTREE      |         |               |
| employees |          1 | idx_a    |            3 | birth_date  | A         |      299468 | NULL     | NULL   |      | BTREE      |         |               |
| employees |          1 | idx_b    |            1 | hire_date   | A         |        6237 | NULL     | NULL   |      | BTREE      |         |               |
| employees |          1 | idx_b    |            2 | birth_date  | A         |      297591 | NULL     | NULL   |      | BTREE      |         |               |
| employees |          1 | idx_b    |            3 | first_name  | A         |      299468 | NULL     | NULL   |      | BTREE      |         |               |
| employees |          1 | idx_c    |            1 | first_name  | A         |        1260 | NULL     | NULL   |      | BTREE      |         |               |
| employees |          1 | idx_c    |            2 | hire_date   | A         |      293517 | NULL     | NULL   |      | BTREE      |         |               |
| employees |          1 | idx_c    |            3 | birth_date  | A         |      299468 | NULL     | NULL   |      | BTREE      |         |               |
| employees |          1 | idx_d    |            1 | first_name  | A         |        1218 | NULL     | NULL   |      | BTREE      |         |               |
| employees |          1 | idx_d    |            2 | birth_date  | A         |      294525 | NULL     | NULL   |      | BTREE      |         |               |
| employees |          1 | idx_d    |            3 | hire_date   | A         |      298095 | NULL     | NULL   |      | BTREE      |         |               |
| employees |          1 | idx_e    |            1 | birth_date  | A         |        4767 | NULL     | NULL   |      | BTREE      |         |               |
| employees |          1 | idx_e    |            2 | first_name  | A         |      292761 | NULL     | NULL   |      | BTREE      |         |               |
| employees |          1 | idx_e    |            3 | hire_date   | A         |      299468 | NULL     | NULL   |      | BTREE      |         |               |
| employees |          1 | idx_f    |            1 | birth_date  | A         |        4767 | NULL     | NULL   |      | BTREE      |         |               |
| employees |          1 | idx_f    |            2 | hire_date   | A         |      297864 | NULL     | NULL   |      | BTREE      |         |               |
| employees |          1 | idx_f    |            3 | first_name  | A         |      299468 | NULL     | NULL   |      | BTREE      |         |               |
+-----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

SQL1

mysql> explain select  emp_no,birth_date,first_name,last_name,gender,hire_date 
from    employees 
where   hire_date >= '1998-01-01'
and     first_name = 'Ebbe'
order by birth_date;
+----+-------------+-----------+------------+-------+-------------------------+-------+---------+------+------+----------+---------------------------------------+
| id | select_type | table     | partitions | type  | possible_keys           | key   | key_len | ref  | rows | filtered | Extra                                 |
+----+-------------+-----------+------------+-------+-------------------------+-------+---------+------+------+----------+---------------------------------------+
|  1 | SIMPLE      | employees | NULL       | range | idx_a,idx_b,idx_c,idx_d | idx_c | 19      | NULL |    5 |   100.00 | Using index condition; Using filesort |
+----+-------------+-----------+------------+-------+-------------------------+-------+---------+------+------+----------+---------------------------------------+

here MySQL Automatically selected idx_c, Because first_name+hire_date Two fields have filtered the data, only 5 That's ok , Because of the lack of data , Sorting is very fast . conversely , If you choose idx_d, You need to pass first_name The fields filter out the qualified 190 Row data , And then use hire_date Filter data , Heavy workload .

SQL2

mysql> explain select  emp_no,birth_date,first_name,last_name,gender,hire_date 
from    employees 
where   hire_date >= '1980-01-01'
and     first_name = 'Ebbe'
order by birth_date;
+----+-------------+-----------+------------+------+-------------------------+-------+---------+-------+------+----------+-----------------------+
| id | select_type | table     | partitions | type | possible_keys           | key   | key_len | ref   | rows | filtered | Extra                 |
+----+-------------+-----------+------------+------+-------------------------+-------+---------+-------+------+----------+-----------------------+
|  1 | SIMPLE      | employees | NULL       | ref  | idx_a,idx_b,idx_c,idx_d | idx_d | 16      | const |  190 |    50.00 | Using index condition |
+----+-------------+-----------+------------+------+-------------------------+-------+---------+-------+------+----------+-----------------------+

If you choose idx_c,first_name+hire_date After two fields filter data through index , Large amount of data , This leads to very slow sorting .MySQL Automatically selected idx_d, By index first_name Columns filter data , And push and filter through index conditions hire_date Field , And then take the data out of the index in order , relatively speaking , Due to the use idx_d There is no need to sort , It will be faster .

( Four ) Composite index summary

1. The creation of Composite Index , If there are multiple equivalent queries , Put the column with good selectivity at the top , The column with poor selectivity is placed at the back ;

2. The creation of Composite Index , If it involves equivalence query and range query , No matter how selective the columns of non equivalent queries are , The field of equivalent query should be put in front of non equivalent query ;

3. The creation of Composite Index , If it involves equivalence query and range query and sorting (order by、group by), The equivalent query is placed at the top of the index , Which comes first in range query or sort , Which is in the back , It needs to be decided according to the actual situation . If the range query comes first , The order of index cannot be used , Need to be filesort, It is suitable for those with less return results SQL, Because less results leads to less sorting overhead ; If you rank first , You can use the order of the index , But I need to return my watch ( Or under index conditions ) Go look up the data , It is suitable for those who return more results SQL, Because there's no need to sort , Take the data directly .

4. The creation of Composite Index , We must not put order by、group by The column of is placed at the top of the index , Because the query always where Precede order by perform ;

5. Using index for range query will result in subsequent index fields not being used , If there is an order , Can't get rid of filesort Sort . Example :a_b_c Indexes ,where a>? and b = ? order by c, be a Can be used to ,b Can't be used ,c Field needs filesort.

原网站

版权声明
本文为[minihuabei]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/175/202206241152195057.html