码迷,mamicode.com
首页 > 数据库 > 详细

Mysql索引

时间:2020-01-27 15:37:23      阅读:81      评论:0      收藏:0      [点我收藏+]

标签:ted   comm   highlight   signed   执行计划   ext   utf8   explain   constrain   

 

高性能的索引策略

1 独立的列

  “独立的列”:索引列不能是表达式的一部分,也不能是参数的参数,必须将索引列单独放在比较符号的一侧

mysql> select actor_id from sakila.actor where actore_id + 1 = 5;【X】
mysql> select ... where to_days(current_date) - to_days(date_col) <= 10;【X】

  

2 前缀索引和索引选择性

有时候需要索引很长的字符串列,但这样会让索引变得很大且慢。这时候需要索引字符串列的一部分字符串,这样可以大大节约索引空间,从而提高索引效率,但是这样有可能降低索引的选择性。

【索引选择性:不重复的索引值(基数)和数据表的记录总数(#T)的比值,范围从1/#T 到 1 之间,索引选择性越高,查询效率越高,因为选择性高的索引可以让mysql过滤掉更多的行】  

我们需要通过特定的方法确认,当前缀索引长度为N时,这N个字符的选择性已经接近整个字段的选择性,如下面例子所示,当N为7时,再增加前缀长度,选择性的增加已经很小。

 

select
count(distinct left(city,3))/count(*) as sel3,
count(distinct left(city,4))/count(*) as sel4,
count(distinct left(city,5))/count(*) as sel5,
count(distinct left(city,6))/count(*) as sel6,
count(distinct left(city,7))/count(*) as sel7
from sakila.city;

+--------+--------+--------+--------+--------+

| sel3   | sel4   | sel5   | sel6   | sel7   |

+--------+--------+--------+--------+--------+

| 0.7633 | 0.9383 | 0.9750 | 0.9900 | 0.9933 |

+--------+--------+--------+--------+--------+

  

增加前缀索引:mysql> alter table sakila.city add key(city(7));

-- 原始ddl,city字段上没有索引
 CREATE TABLE `city` (
  `city_id` smallint(5) unsigned NOT NULL AUTO_INCREMENT,
  `city` varchar(50) NOT NULL,
  `country_id` smallint(5) unsigned NOT NULL,
  `last_update` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`city_id`),
  KEY `idx_fk_country_id` (`country_id`),
  KEY `city` (`city`(7)),
  CONSTRAINT `fk_city_country` FOREIGN KEY (`country_id`) REFERENCES `country` (`country_id`) ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=601 DEFAULT CHARSET=utf8mb4

-- 查询的执行计划
mysql> explain select * from city where city = ‘Ahmadnagar‘;
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra       |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | city  | NULL       | ALL  | NULL          | NULL | NULL    | NULL |  600 |    10.00 | Using where |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

-- 增加city字段索引后的ddl
 CREATE TABLE `city` (
  `city_id` smallint(5) unsigned NOT NULL AUTO_INCREMENT,
  `city` varchar(50) NOT NULL,
  `country_id` smallint(5) unsigned NOT NULL,
  `last_update` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`city_id`),
  KEY `idx_fk_country_id` (`country_id`),
  KEY `city` (`city`(7)),
  CONSTRAINT `fk_city_country` FOREIGN KEY (`country_id`) REFERENCES `country` (`country_id`) ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=601 DEFAULT CHARSET=utf8mb4

-- 查询的执行计划,查询已经可以走上索引了。
mysql> explain select * from city where city = ‘Ahmadnagar‘;
+----+-------------+-------+------------+------+---------------+------+---------+-------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref   | rows | filtered | Extra       |
+----+-------------+-------+------------+------+---------------+------+---------+-------+------+----------+-------------+
|  1 | SIMPLE      | city  | NULL       | ref  | city          | city | 30      | const |    1 |   100.00 | Using where |
+----+-------------+-------+------------+------+---------------+------+---------+-------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

 前缀索引是一种能让索引更小、更快的方法,但是也有缺点:

  1. 无法使用前缀索引做order by 和 group by
  2. 无法使用前缀索引做覆盖扫描

 3 多列索引

 

CREATE TABLE `film_actor_test` (
  `actor_id` smallint(5) unsigned NOT NULL,
  `film_id` smallint(5) unsigned NOT NULL,
  `last_update` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  KEY `actor_id` (`actor_id`),
  KEY `film_id` (`film_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1


mysql> explain select film_id,actor_id from sakila.film_actor_test where actor_id = 1 or film_id = 1 \G;
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: film_actor_test
   partitions: NULL
         type: index_merge
possible_keys: actor_id,film_id
          key: actor_id,film_id
      key_len: 2,2
          ref: NULL
         rows: 29
     filtered: 100.00
        Extra: Using union(actor_id,film_id); Using where
1 row in set, 1 warning (0.00 sec)

  

  

Mysql索引

标签:ted   comm   highlight   signed   执行计划   ext   utf8   explain   constrain   

原文地址:https://www.cnblogs.com/wooluwalker/p/12235877.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!