ICode9

精准搜索请尝试: 精确搜索
首页 > 数据库> 文章详细

数据库索引的设计与优化(一)

2021-05-12 17:57:16  阅读:120  来源: 互联网

标签:-- where 数据库 查询 索引 使用 优化 select


1、索引的原理

首先要先了解索引是什么,例如这样一个查询:select * from table1 where id=10000。如果没有索引,必须遍历整个表,直到ID等于10000的这一行被找到为止;有了索引之后(必须是在ID这一列上建立的索引),即可在索引中查找。由于索引是经过某种算法优化过的,因而查找次数要少的多。可见,索引是用来定位的

2、索引的分类

索引分为聚簇索引非聚簇索引两种,聚簇索引是按照数据存放的物理位置为顺序的,而非聚簇索引则不同;聚簇索引能提高多行检索的速度,而非聚簇索引对于单行的检索很快。
MyISAM是非聚簇索引,B+Tree的叶子节点上的data,并不是数据本身,而是数据存放的地址。
InnoDB使用的是聚簇索引,将主键组织到一棵B+树中,而行数据就储存在叶子节点上,如果查找Name,会先用Name查找存储数据的id,再根据id获取整行数据。

mysql的索引根据功能分为单列索引主键索引,唯一索引,普通索引)和组合索引

  1. 主键索引:是一种特殊的唯一索引,一个表只能有一个主键,不允许有空值。一般是在建表的时候同时创建主键索引。
  2. 唯一索引:索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必须唯一。
  3. 普通索引:最基本的索引,它没有任何限制,用于加速查询。
  4. 组合索引:指多个字段上创建的索引,只有在查询条件中使用了创建索引时的第一个字段,索引才会被使用。使用组合索引时遵循最左前缀集合。

举个例子:建一个表CREATE TABLE mytable( ID INT NOT NULL, username VARCHAR(16) NOT NULL, city VARCHAR(50) NOT NULL, age INT NOT NULL );为了进一步榨取MySQL的效率,建立组合索引,将name,city,age建到一个索引里:ALTER TABLE mytable ADD INDEX name_city_age(name(10),city,age);

建表时,username的长度为16,这里用10.根据实际情况名字的长度一般不会超过10,这样会加速索引查询速度,减少索引文件的大小,提高INSERT的更新速度。

建立这样的组合索引,相当于分别建立了下面三组索引:
username;username city; username city age 根据MySQL组合索引最左前缀原则,所以并没有city age的组合。

3、索引的优化

1、Explain优化查询检测

explain 可以帮助开发人员分析SQL问题,explain显示了mysql如何使用索引来处理select语句以及连接表,可以帮助选择更好的索引和写出更优化的查询语句。
使用方法在select语句前加上explain:

Explain select * from logs where false;

mysql 在执行一条查询前,会对发出的每条SQL进行分析,决定是否使用索引或全表扫描。如果发送一条上述查询语句,Mysql是不会执行查询操作的,因为经过sql分析器的分析后Mysql已经清楚不会有任何语句符合操作。
实例

mysql> EXPLAIN SELECT `birday` FROM `user` WHERE `birthday` < "1990/2/2"; 
-- 结果: 
id: 1 

select_type: SIMPLE -- 查询类型(简单查询、联合查询、子查询) 

table: user -- 显示这一行的数据是关于哪张表的 。

type: range -- 区间索引(在小于1990/2/2区间的数据),这是重要的列,显示连接使用了何种类型。从最好到最差的连接类型为system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL,const代表一次就命中,ALL代表扫描了全表才确定结果。一般来说,得保证查询至少达到range级别,最好能达到ref。 

possible_keys: birthday  -- 指出MySQL能使用哪个索引在该表中找到行。如果是空的,没有相关的索引。这时要提高性能,可通过检验WHERE子句,看是否引用某些字段,或者检查字段不是适合索引。  

key: birthday -- 实际使用到的索引。如果为NULL,则没有使用索引。如果为primary的话,表示使用了主键。 

key_len: 4 -- 最长的索引宽度。如果键是NULL,长度就是NULL。在不损失精确性的情况下,长度越短越好。

ref: const -- 显示哪个字段或常数与key一起被使用。  

rows: 1 -- 这个数表示mysql要遍历多少数据才能找到,在innodb上是不准确的。 

Extra: Using where; Using index -- 执行状态说明,这里可以看到的坏的例子是Using temporary和Using

select_type

  1. simple:简单select(不使用union或子查询)
  2. primary:最外面的select
  3. union:union中的第二个或后面的select语句
  4. dependent union:union中的第二个或后面的select语句,取决于外面的查询
  5. union result:union的结果
  6. subquery:子查询中的第一个select
  7. dependent subquery:子查询中的第一个select,取决于外面的查询
  8. derived:导出表的select(from子句的子查询)

其它查询结果项
其中type

  1. 如果是Only index,这意味着信息只用于索引树中的信息检索出来的,比扫描整个表要快
  2. 如果是where used,就是使用上了where的限制
  3. 如果是impossible where 表示用不着where,一般就是没查出来什么啥
  4. 如果此信息显示Using filesort或者Using temporary的话会很吃力,where和order by的索引经常无法兼顾,如果按照where来确定索引,那么在order by时,就必然会引起Using filesort,这就要看是先过滤再排序划算,还是先排序再过滤划算
2、创建索引的技巧
  1. 维度高的列创建索引
  2. 数据列中不重复值出现的个数,这个数量越高,维度就越高
  3. 要为纬度高的列创建索引,如性别和年龄,那年龄的维度就高于性别,性别这样的列不适合创建索引,因为维度过低
  4. 对where,on,group by,order by中出现的列使用索引
  5. 对长度较小的数据列使用索引,这样会使索引的文件更小,同时内存中可以装载更多的索引键
  6. 为较长的字符串使用前缀索引
  7. 不要过多的创建索引,除了增加额外的磁盘空间外,对DML操作的速度影响很大,因为每增删改查一次就要重新建立索引
  8. 使用组合索引,可以减少文件索引的大小,在使用时速度要优于多个单列索引
3、什么样的sql不走索引
  1. 索引列参与了计算
  2. 索引列使用了函数运算
  3. LIKE中%在后边是走索引的,在前面不走索引
  4. 正则表达式不走索引
  5. 字符串与数字比较不使用索引,例如where ‘a’=“1” --走索引;where ‘a’=1 --不走索引
  6. 条件中使用or,除非使用的所有字段都建立索引,否则不会使用索引,建议尽量避免使用or关键字
  7. 如果mysql估计使用全表扫描比使用索引快,则不使用索引

4、索引的弊端

不能盲目创建索引,只为查询频繁的列创建索引,创建索引会使查询操作变得更加快速,但会降低增删改查操作的速度,因为执行这些操作的同时会对索引文件进行重新排序或更新。
但是,在互联网应用汇中,查询语句远远大于DML语句,甚至可以占到80%~90%,也不用过于在意,只是在大量数据导入时,可以考虑先删除索引,再批量插入数据,最后再添加索引。

文章有参考:https://www.runoob.com/w3cnote/mysql-index.html

标签:--,where,数据库,查询,索引,使用,优化,select
来源: https://blog.csdn.net/weixin_47103265/article/details/115377241

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有