# 有这样一个表 P

mysql> create table P (id int primary key, name varchar(10) not null, sex varchar(1), age int, index tl(name,sex,age)) engine=IInnoDB;

mysql> insert into P values(1,'张三','F',26),(2,'张三','M',27),(3,'李四','F',28),(4,'乌兹','F',22),(5,'张三','M',21),(6,'王五','M',28);

# 下面的语句结果相同

mysql> select * from P where name='张三' and sex='F';     ## A1

mysql> select * from P where sex='F' and age=26;         ## A2

# explain 看一下

mysql> explain select * from P where name='张三' and sex='F';

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

| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref         | rows | filtered | Extra       |

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

|  1 | SIMPLE      | P     | NULL       | ref  | tl            | tl   | 38      | const,const |    1 |   100.00 | Using index |

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

mysql> explain select * from P where sex='F' and age=26;

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

| id | select_type | table | partitions | type  | possible_keys | key  | key_len | ref  | rows | filtered | Extra                    |

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

|  1 | SIMPLE      | P     | NULL       | index | NULL          | tl   | 43      | NULL |    6 |    16.67 | Using where; Using index |

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

可以清楚的看到,A1 使用 tl 索引,A2 进行了全表扫描,虽然 A2 的两个条件都在 tl 索引中出现,但是没有使用到 name 列,不符合最左前缀原则,无法使用索引。所以在建立联合索引的时候,如何安排索引内的字段排序是关键。评估标准是索引的复用能力,因为支持最左前缀,所以当建立(a,b)这个联合索引之后,就不需要给 a 单独建立索引。原则上,如果通过调整顺序,可以少维护一个索引,那么这个顺序往往就是需要优先考虑采用的。上面这个例子中,如果查询条件里只有 b,就是没法利用(a,b)这个联合索引的,这时候就不得不维护另一个索引,也就是说要同时维护(a,b)、(b)两个索引。这样的话,就需要考虑空间占用了,比如,name 和 age 的联合索引,name 字段比 age 字段占用空间大,所以创建(name,age)联合索引和(age)索引占用空间是要小于(age,name)、(name)索引的。

2.3 索引下推

以人员表的联合索引(name, age)为例。如果现在有一个需求:检索出表中“名字第一个字是张,而且年龄是26岁的所有男性”。那么,SQL 语句是这么写的mysql> select * from tuser where name like '张%' and age=26 and sex=M;

通过最左前缀索引规则,会找到 ID1,然后需要判断其他条件是否满足在 MySQL 5.6 之前,只能从 ID1 开始一个个回表。到主键索引上找出数据行,再对比字段值。而 MySQL 5.6 引入的索引下推优化(index condition pushdown),可以在索引遍历过程中,对索引中包含的字段先做判断,直接过滤掉不满足条件的记录,减少回表次数。这样,减少了回表次数和之后再次过滤的工作量,明显提高检索速度。

2.4 隐式类型转化

隐式类型转化主要原因是,表结构中指定的数据类型与传入的数据类型不同,导致索引无法使用。所以有两种方案:

修改表结构,修改字段数据类型。

修改应用,将应用中传入的字符类型改为与表结构相同类型。

3. 为什么会选错索引3.1 优化器选择索引是优化器的工作,其目的是找到一个最优的执行方案,用最小的代价去执行语句。在数据库中,扫描行数是影响执行代价的因素之一。扫描的行数越少,意味着访问磁盘数据的次数越少,消耗的 CPU 资源越少。当然,扫描行数并不是唯一的判断标准,优化器还会结合是否使用临时表、是否排序等因素进行综合判断。

3.2 扫描行数

MySQL 在真正开始执行语句之前,并不能精确的知道满足这个条件的记录有多少条,只能通过索引的区分度来判断。显然,一个索引上不同的值越多,索引的区分度就越好,而一个索引上不同值的个数我们称为“基数”,也就是说,这个基数越大,索引的区分度越好。# 通过 show index 方法,查看索引的基数mysql> show index from t;+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+| t     |          0 | PRIMARY  |            1 | id          | A         |       95636 |     NULL | NULL   |      | BTREE      |         |               || t     |          1 | a        |            1 | a           | A         |       96436 |     NULL | NULL   | YES  | BTREE      |         |               || t     |          1 | b        |            1 | b           | A         |       96436 |     NULL | NULL   | YES  | BTREE      |         |               |+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

MySQL 使用采样统计方法来估算基数:采样统计的时候,InnoDB 默认会选择 N 个数据页,统计这些页面上的不同值,得到一个平均值,然后乘以这个索引的页面数,就得到了这个索引的基数。而数据表是会持续更新的,索引统计信息也不会固定不变。所以,当变更的数据行数超过 1/M 的时候,会自动触发重新做一次索引统计。

在 MySQL 中,有两种存储索引统计的方式,可以通过设置参数 innodb_stats_persistent 的值来选择:

on 表示统计信息会持久化存储。默认 N = 20,M = 10。

off 表示统计信息只存储在内存中。默认 N = 8,M = 16。

由于是采样统计,所以不管 N 是 20 还是 8,这个基数都很容易不准确。所以,冤有头债有主,MySQL 选错索引,还得归咎到没能准确地判断出扫描行数。

可以用 analyze table 来重新统计索引信息,进行修正。

ANALYZE [LOCAL | NO_WRITE_TO_BINLOG] TABLE tbl_name [, tbl_name] ...

3.3 索引选择异常和处理1. 采用 force index 强行选择一个索引。2. 可以考虑修改语句,引导 MySQL 使用我们期望的索引。3. 有些场景下,可以新建一个更合适的索引,来提供给优化器做选择,或删掉误用的索引。

大文本存mysql怎么建索引_如何正确合理的建立MYSQL数据库索引相关推荐

  1. mysql gis index 索引原理_从原理到优化,深入浅出数据库索引

    MySQL官方对索引的定义为:索引(Index)是帮助MySQL高效获取数据的数据结构. 数据库查询是数据库的最主要功能之一,我们都希望查询数据的速度能尽可能的快,因此数据库系统的设计者会从查询算法的 ...

  2. 联合索引会创建几个索引_面试官:谈谈你对mysql联合索引的认识?

    引言 这篇文章作为<面试官:谈谈你对mysql索引的认识>的续篇,我当时在写这篇的时候,考虑到篇幅问题所以略去了联合索引的内容,今天给大家补上. 本文预计分为两个部分:(1)联合索引部分的 ...

  3. 2 创建联合索引_想进大厂,这些Mysql索引底层知识你是必须知道的

    推荐学习 阿里P8MySQL,基础/索引/锁/日志/调优都不误,一锅深扒端给你 最新Java岗面试清单:分布式+Dubbo+线程+Redis+数据库+JVM+并发 前言 这一篇是讲解Mysql中做使用 ...

  4. mysql 回滚段_史上最牛分析MySQL索引机制的实现!不接受反驳

    数据库是一个只要从事后端开发,就永远离不开的技术,大部分企业选择的数据库都是MySQL,所以需要我们对MySQL有着足够的了解. 而MySQL索引,我们都知道提高性能要加索引,也知道索引的结构是B-T ...

  5. mysql explain 为空_车祸现场!我的MySQL千万级数据表选错索引了!

    最近在线上环境遇到了一次SQL慢查询引发的数据库故障,影响线上业务.经过排查后,确定原因是:SQL在执行时,MySQL优化器选择了错误的索引(不应该说是"错误",而是选择了实际执行 ...

  6. access建立两个字段唯一索引_面试官:谈谈你对mysql索引的认识?

    引言 这篇我们就来谈谈关于索引方面的mysql面试题.还是老规矩,讲的是在Innodb存储引擎下的情形,毕竟我还真没用过Mysiam之类的存储引擎. ps:其实很早就想写了,一直偷懒! 其实这下面每个 ...

  7. db2 删除索引_史上最牛分析MySQL索引机制的实现!不接受反驳!

    作者:陌北有棵树,爱玩Java,架构师社区合伙人! 数据库是一个只要从事后端开发,就永远离不开的技术,大部分企业选择的数据库都是MySQL,所以需要我们对MySQL有着足够的了解. 而MySQL索引, ...

  8. mysql负载均衡分区_分区和负载均衡让MySQL更大更好

    通常,当我们的MySQL数据库逐渐变慢时,我们就希望通过一切努力使它变得更快.更强.更大.更好!那么都有哪些方法呢?别着急,我会一个一个给大家介 绍如何才能实现这些美好的愿望.阅读本系列文章将有助于扩 ...

  9. mysql 红黑树_微信大牛教你深入了解数据库索引

    | 作者刘国斌,腾讯微信事业群研发工程师,目前从事企业微信的后台研发工作,已经参与企业微信消息系统.群聊.客户联系等企业微信多个核心功能的迭代. 数据库查询是数据库的最主要功能之一. 我们都希望查询数 ...

最新文章

  1. 阿里规范不建议多表join,可这SQL要怎么写啊?
  2. 极大似然估计_计量经济学 | 极大似然估计
  3. tar exclue文件夹
  4. ubuntu14.04下通过.frm, .MYD,.MYI文件恢复建立mysql数据库
  5. mysql access 2017_如何把Access的数据导入到Mysql中
  6. boost::statechart模块测量 BitMachine 的事件处理性能的测试程序
  7. SparkSQL愿景
  8. python中深拷贝和浅拷贝
  9. android微信风格,Android开发实现模仿微信小窗口功能【Dialog对话框风格窗口】
  10. Git学习总结(9)——如何构建你自己的 Git 服务器
  11. 服务器的数据库文件是哪个文件夹,Oracle数据库服务器参数文件管理技巧是什么?...
  12. Supervisor使用说明
  13. 【HDU】4391 Paint The Wall
  14. css元素居中的几种方式
  15. 在禁用uac_如何(真正)在Windows 7上完全禁用UAC
  16. c语言pow函数原型_C语言pow函数
  17. java基础-对15位或18位身份证号码的验证
  18. Jenkins项目自动化部署工具的安装、配置及使用
  19. Unity制作AR图片和视频展示
  20. c++逆天改命进阶--继承

热门文章

  1. SAP Marketing Cloud的双重登录认证
  2. Cloud for Customer的mobile setting前台实现
  3. is transfer = C ( only read dynamically) not supported in one order scenario
  4. jQuery.proxy debug
  5. What is the usage of Transfer field in Text determine procedure customizing
  6. 创建简单的xslt transformation
  7. 使用Asynchronous RFC call 拆分time consuming task
  8. 给硬件工程师介绍SAP Cloud for Customer
  9. ubuntu如何进入超级权限模式,退出超级权限模式,sudo su——root权限
  10. 外星人进化_深层分析宇宙常数对生命形成进化的影响,外星人或许根本就“不是人”!...