mysql——index, one article explains it clearly!

Intuitive experience - data preparation

Create table and insert data

CREATE TABLE `user` (
  `uid` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) DEFAULT NULL,
  `pwd` varchar(50) DEFAULT NULL,
  `create_time` datetime DEFAULT NULL,
  `modify_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `rids` varchar(15) DEFAULT NULL,
  `nickname` varchar(45) DEFAULT NULL,
  `company` varchar(15) DEFAULT NULL,
  PRIMARY KEY (`uid`),
  UNIQUE KEY `name_UNIQUE` (`name`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8
INSERT INTO `monitor`.`user`(`uid`, `name`, `pwd`, `create_time`, `modify_time`, `rids`, `nickname`, `company`) VALUES (1, 'rocker', 'rocker', NULL, '2019-10-08 11:05:02', '1', 'rocker', 'rocker');
INSERT INTO `monitor`.`user`(`uid`, `name`, `pwd`, `create_time`, `modify_time`, `rids`, `nickname`, `company`) VALUES (2, 'danny', 'danny', NULL, '2019-10-08 11:31:36', '2', 'rocker', 'danny');
INSERT INTO `monitor`.`user`(`uid`, `name`, `pwd`, `create_time`, `modify_time`, `rids`, `nickname`, `company`) VALUES (3, 'tom', 'tom', NULL, '2019-10-08 11:31:39', '1', 'tom', 'rocker');
INSERT INTO `monitor`.`user`(`uid`, `name`, `pwd`, `create_time`, `modify_time`, `rids`, `nickname`, `company`) VALUES (4, 'messi', 'messi', NULL, '2019-10-08 11:31:21', '2', 'messi', 'messi');
INSERT INTO `monitor`.`user`(`uid`, `name`, `pwd`, `create_time`, `modify_time`, `rids`, `nickname`, `company`) VALUES (5, 'wenger', 'wenger', NULL, '2019-10-08 11:29:38', '1', 'wenger', 'rocker');
INSERT INTO `monitor`.`user`(`uid`, `name`, `pwd`, `create_time`, `modify_time`, `rids`, `nickname`, `company`) VALUES (6, 'henry', 'henry', NULL, '2019-10-08 11:30:46', '2', 'henry', 'henry');
INSERT INTO `monitor`.`user`(`uid`, `name`, `pwd`, `create_time`, `modify_time`, `rids`, `nickname`, `company`) VALUES (7, 'ronaldo', 'ronaldo', NULL, '2019-10-08 11:30:49', '1', 'ronaldo', 'ronaldo');
INSERT INTO `monitor`.`user`(`uid`, `name`, `pwd`, `create_time`, `modify_time`, `rids`, `nickname`, `company`) VALUES (8, 'kaka', 'kaka', NULL, '2019-10-08 11:29:45', '2', 'kaka', 'rocker');

explain introduction - analyze the select statement

name meaning other
select_type Commonly used are SIMPLE simple query, UNION combined query, SUBQUERY sub query, etc.
table the table to query
possible_keys The possible indexes to choose optional index
key The index actually chosen the actual index used
rows Estimate of rows to be examined number of rows scanned
type index query type Frequently used index query types:
const: When using the primary key or unique index for query, only one row matches. When using the primary key or unique index for query, only one row matches.
ref: Use a non-unique index
eq_ref Trigger condition: When performing a join query, use a primary key or a unique index and only match one row of records
range: Use a primary key, an auxiliary index for a single field, or the last field of an auxiliary index for multiple fields Perform range query
all: Scan the entire table index: The difference from all is that the index tree system
is scanned. Trigger condition: The table has only one row, which is a special case of const type.

Analysis - Individual Indexes vs Composite Indexes

1. No indexing

First, execute a query statement without indexing the two fields of 'nickname' and 'company', and analyze

mysql> explain select * from user where nickname = 'rocker' and company = 'rocker';
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra       |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | user  | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    8 |    12.50 | Using where |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

It can be seen that without indexing, a total of 8 pieces of data have been queried, and there are also 8 pieces of data in the table, which is equivalent to a full table scan.

mysql> explain select * from user where company = 'rocker' or nickname = 'rocker';
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra       |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | user  | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    8 |    23.44 | Using where |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

It can be seen that without any index, whether it is and or or, it is a full table scan without an index.

2. Separate index

Add indexes to nickname and company respectively, and then execute the sql query of and and or

alter table user add index `idx_nickname` (`nickname`);
alter table user add index `idx_company` (`company`);

Execute the query statement and

mysql> explain select * from user where nickname = 'rocker' and company = 'rocker';
+----+-------------+-------+------+--------------------------+--------------+---------+-------+------+-------------+
| id | select_type | table | type | possible_keys            | key          | key_len | ref   | rows | Extra       |
+----+-------------+-------+------+--------------------------+--------------+---------+-------+------+-------------+
|  1 | SIMPLE      | user  | ref  | idx_nickname,idx_company | idx_nickname | 138     | const |    2 | Using where |
+----+-------------+-------+------+--------------------------+--------------+---------+-------+------+-------------+
1 row in set (0.05 sec)

Execute the query or

mysql> explain select * from user where company = 'rocker' or nickname = 'rocker';
+----+-------------+-------+------+--------------------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys            | key  | key_len | ref  | rows | Extra       |
+----+-------------+-------+------+--------------------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | user  | ALL  | idx_nickname,idx_company | NULL | NULL    | NULL |    8 | Using where |
+----+-------------+-------+------+--------------------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)

can be seen:

  • After adding the index, the and query can use the index, but only one index works, and the other index field still needs to be traversed, and the and query will choose which one to use according to the high correlation (the number of rows that meet this condition is small) index
  • or query without index

3. Composite index

Delete the original separate index and add a combined index

alter table user drop index `idx_nickname`
alter table user drop index `idx_company`
alter table user add index `idx_composition` (`nickname`,`company`);

Execute the query statement and

mysql> explain select * from user where nickname = 'rocker' and company = 'rocker';
+----+-------------+-------+------+-----------------+-----------------+---------+-------------+------+-------------+
| id | select_type | table | type | possible_keys   | key             | key_len | ref         | rows | Extra       |
+----+-------------+-------+------+-----------------+-----------------+---------+-------------+------+-------------+
|  1 | SIMPLE      | user  | ref  | idx_composition | idx_composition | 186     | const,const |    1 | Using where |
+----+-------------+-------+------+-----------------+-----------------+---------+-------------+------+-------------+
1 row in set (0.00 sec)

Execute the query or

mysql> explain select * from user where company = 'rocker' or nickname = 'rocker';
+----+-------------+-------+------+-----------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys   | key  | key_len | ref  | rows | Extra       |
+----+-------------+-------+------+-----------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | user  | ALL  | idx_composition | NULL | NULL    | NULL |    8 | Using where |
+----+-------------+-------+------+-----------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)

It can be seen that after the combined index is added, the combined index works, and only one piece of data that meets the result needs to be queried, which is more efficient than a single index.

But composite index doesn't work for or query

4. Combined index query single index column

For the case where the combined index is in the order of (nickname, company)

alter table user drop index `idx_composition`;
alter table user add index `idx_composition` (`nickname`,`company`);
mysql> explain select * from user where nickname = 'rocker';
+----+-------------+-------+------+-----------------+-----------------+---------+-------+------+-------------+
| id | select_type | table | type | possible_keys   | key             | key_len | ref   | rows | Extra       |
+----+-------------+-------+------+-----------------+-----------------+---------+-------+------+-------------+
|  1 | SIMPLE      | user  | ref  | idx_composition | idx_composition | 138     | const |    2 | Using where |
+----+-------------+-------+------+-----------------+-----------------+---------+-------+------+-------------+
1 row in set (0.00 sec)
mysql> explain select * from user where company = 'rocker';
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | user  | ALL  | NULL          | NULL | NULL    | NULL |    8 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)

It can be seen that when nickname is first in the combined index, querying nickname alone will go to the index, and querying compamy alone will not go to the index

For the case where the combined index is in the order of (company, nickname)

alter table user drop index `idx_composition`;
alter table user add index `idx_composition` (`company`,`nickname`);
mysql> explain select * from user where nickname = 'rocker';
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | user  | ALL  | NULL          | NULL | NULL    | NULL |    8 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)
mysql> explain select * from user where company = 'rocker';
+----+-------------+-------+------+-----------------+-----------------+---------+-------+------+-------------+
| id | select_type | table | type | possible_keys   | key             | key_len | ref   | rows | Extra       |
+----+-------------+-------+------+-----------------+-----------------+---------+-------+------+-------------+
|  1 | SIMPLE      | user  | ref  | idx_composition | idx_composition | 48      | const |    2 | Using where |
+----+-------------+-------+------+-----------------+-----------------+---------+-------+------+-------------+
1 row in set (0.00 sec)

It can be seen that when compamy is in the front of the combined index, querying compamy alone will go to the index, and querying nickname alone will not go to the index

If the composite index is (A, B), then for the condition A=a, this composite index can be used, because the composite index is sorted according to the first column first, so there is no need to create a separate index for A, but It is not used for B=b, because the second column is compared only when the first column is the same, so the second column is the same, and can be distributed on different nodes, and there is no way to quickly locate

Advantages of Indexing

  • Significantly reduces the number of data rows that the server needs to scan.

  • Help the server avoid sorting and grouping, and avoid creating temporary tables (B+Tree indexes are ordered and can be used for ORDER BY and GROUP BY operations. Temporary tables are mainly created during sorting and grouping, and do not require sorting and grouping , there is no need to create a temporary table).

  • Change random I/O into sequential I/O (B+Tree indexes are ordered and store adjacent data together).

The underlying principle: comparison of B, B+, red-black tree, and AVL tree

see another blog

MySQL index type

Indexing is implemented at the storage engine layer, not at the server layer, so different storage engines have different index types and implementations.

B+ Tree index

Is the default index type for most MySQL storage engines.

Because there is no need to perform a full table scan, only the tree needs to be searched, so the search speed is much faster.

Because of the ordered nature of B+ Tree, it can also be used for sorting and grouping in addition to searching.

You can specify multiple columns as index columns, and multiple index columns together form a key.

Applicable to full key value, key value range and key prefix lookup, where key prefix lookup is only applicable to leftmost prefix lookup. Indexes cannot be used if lookups are not done in the order of the indexed columns.

InnoDB's B+Tree index is divided into primary index and auxiliary index. The data domain of the leaf node of the main index records complete data records, and this index method is called a clustered index. Because there is no way to store data rows in two different places, a table can have only one clustered index.

insert image description here
The data field of the leaf node of the auxiliary index records the value of the primary key. Therefore, when using the auxiliary index to search, you need to find the primary key value first, and then search in the main index. This process is also called returning to the table.

insert image description here

hash index

Hash indexes can be looked up in O(1) time, but lose order:

Cannot be used for sorting and grouping;
only exact search is supported, and cannot be used for partial search and range search.
The InnoDB storage engine has a special function called "adaptive hash index". When an index value is used very frequently, a hash index will be created on top of the B+Tree index, so that the B+Tree Indexes have some of the advantages of hash indexes, such as fast hash lookups.

full text index

The MyISAM storage engine supports full-text indexing, which is used to find keywords in text, rather than directly comparing whether they are equal.

Lookup conditions use MATCH AGAINST instead of plain WHERE.

The full-text index is implemented using an inverted index, which records the mapping of keywords to the documents in which they are located.

The InnoDB storage engine also began to support full-text indexing in MySQL 5.6.4.

Spatial Data Index

The MyISAM storage engine supports spatial data indexes (R-Tree), which can be used for geographic data storage. The spatial data index will index data from all dimensions, and can effectively use any dimension to perform combined queries.

Data must be maintained using GIS-related functions.

index optimization

  • Independent columns
    Indexed columns cannot be part of expressions or parameters of functions when performing queries, otherwise the index cannot be used.
    For example, the following query cannot use the index on the actor_id column:
    SELECT actor_id FROM sakila.actor WHERE actor_id + 1 = 5;
  • Multi-column indexes
    When you need to use multiple columns as conditions for queries, using multi-column indexes is better than using multiple single-column indexes. For example, in the following statement, it is better to set actor_id and film_id as multi-column indexes.
    SELECT film_id, actor_id FROM sakila. film_actor
    WHERE actor_id = 1 AND film_id = 1;
  • The order of the index columns
    puts the most selective index columns first.
    Index selectivity refers to the ratio of unique index values ​​to the total number of records. The maximum value is 1, at this time each record has a unique index corresponding to it. The higher the selectivity, the higher the discrimination of each record and the higher the query efficiency.
    For example, in the results shown below, customer_id is more selective than staff_id, so it is better to put the customer_id column in front of the multi-column index.
SELECT COUNT(DISTINCT staff_id)/COUNT(*) AS staff_id_selectivity,
COUNT(DISTINCT customer_id)/COUNT(*) AS customer_id_selectivity,
COUNT(*)
FROM payment;
   staff_id_selectivity: 0.0001
customer_id_selectivity: 0.0373
               COUNT(*): 16049
  • Prefix index
    For columns of BLOB, TEXT and VARCHAR types, you must use a prefix index, which only indexes the first part of characters.
    The selection of the prefix length needs to be determined according to the index selectivity.

  • Covering index
    An index that contains all the values ​​of the fields that need to be queried.
    It has the following advantages:
    the index is usually much smaller than the size of the data row, and only reading the index can greatly reduce the amount of data access.
    Some storage engines (such as MyISAM) only cache indexes in memory, and the data relies on the operating system to cache. Therefore, accessing only the index can avoid using system calls (which are usually time-consuming).
    For the InnoDB engine, there is no need to access the primary index if the secondary index can cover the query.

Index usage conditions

For very small tables, a simple full table scan is more efficient than indexing in most cases;

For medium to large tables, indexes are very effective;

But for very large tables, the cost of creating and maintaining indexes will increase accordingly. In this case, it is necessary to use a technology that can directly distinguish a set of data that needs to be queried, instead of matching records one by one, for example, partitioning technology can be used.

Why is a simple full table scan more efficient than indexing in most cases for very small tables?

If a table is relatively small, it is obviously faster to traverse the table directly than to go through the index (because it needs to go back to the table).

Note: First of all, it should be noted that the implicit condition of this answer is that the queried data is not a part of the index, and no return table operation is required. Secondly, the query condition is not the primary key, otherwise the data can be obtained directly from the clustered index.

Other - the essence of order_by also belongs to the query! Also add an index (joint index)

Why does the primary key index recommend id auto-increment

1) If we define the primary key (PRIMARY KEY), then InnoDB will choose the primary key as the clustered index.

2) If no primary key is explicitly defined, InnoDB will select the first unique index that does not contain NULL values ​​as the primary key index.

3) If there is no such unique index, InnoDB will choose the built-in 6-byte long ROWID as a hidden clustered index, which will increment the primary key as row records are written.

Author: javacoo
Link: https://www.jianshu.com/p/8adfe1fc511f
Source: Jianshu
The copyright belongs to the author. For commercial reprint, please contact the author for authorization, for non-commercial reprint, please indicate the source.

Guess you like

Origin blog.csdn.net/S_ZaiJiangHu/article/details/130029699