• 数据库索引之优化查询速度


    (一)索引的作用
    索引通俗来讲就相当于书的目录,当我们根据条件查询的时候,没有索引,便需要全表扫描,数据量少还可以,一旦数据量超过百万甚至千万,一条查询sql执行往往需要几十秒甚至更多,5秒以上就已经让人难以忍受了。

    提升查询速度的方向一是提升硬件(内存、cpu、硬盘),二是在软件上优化(加索引、优化sql)。

    (二)mysql的索引类型:
    mysql的索引有5种:主键索引、普通索引、唯一索引、全文索引、聚合索引(多列索引)。

    1)主键索引:主键索引是加在主键上的索引,设置主键(primary key)的时候,它是一种特殊的唯一索引,不允许有空值。一般是在建表的时候同时创建主键索引;

    2)普通索引:创建在非主键列上的索引,这是最基本的索引;

    3)唯一索引:索引列的值必须唯一,但允许有空值。

    4)聚合索引:创建在多列上的索引。

    (三)索引的语法:
    查看某张表的索引:show index from 表名;

    创建普通索引:alter table 表名 add index  索引名 (加索引的列) 

    创建聚合索引:alter table 表名 add index  索引名 (加索引的列1,加索引的列2) 

    删除某张表的索引:drop index 索引名 on 表名;

    (四)关于面试如何通过索引说数据库优化能力
    数据库方面的技能要求,包括三个方面:

      第一,基本的增删改查,存储过程等技能,是否会用些group by,having,distinct,exist,in,with等高级点的语句,

      第二,有没有设计表的经验,

      第三也是关键一点,在数据库优化方面,你是否有相关经验。

      索引是数据库优化所必需的工具,一般会问以下两方面的问题:

    ①索引有什么代价?哪些场景下你需要建索引?或者有时候反过来问,哪些场景下不推荐建索引。

    ②建好索引之后,怎么才能最高效地利用索引?或者反过来问,请说出一个无法有效利用已建索引的案例。

      从结构上来看,索引好比是一棵B树(也叫B*或者B+),假设学生表里只有学生ID和姓名两列,该学生表里有1000个学生,学号分别从1到1000,如果针对ID建立索引,大致的结构如下图所示。

    如果我们要查找ID为111的学生,则数据库系统就会走索引,根据根节点的指引,会找到第二层从左往右第二个数据块,以此类推,会在第四层里得到ID为111的物理地址,然后直接从硬盘里找数据。反过来,如果没有建索引,数据库系统可能就要从一个大的范围里逐一定位查找,效率就没这么高了。

    代价呢?

    1索引需要占硬盘空间,这是空间方面的代价。
    2一旦插入新的数据,就需要重新建索引,这是时间上的代价。
    场景一,数据表规模不大(几千行),即使不建索引,查询语句的返回时间也不长,这时建索引的意义就不大。“性价比”不高。

    场景二,某个商品表里有几百万条商品信息,同时每天会在一个时间点,往其中更新大概十万条左右的商品信息,现在用where语句查询特定商品时(比如wherename=‘XXX’)速度很慢。为了提升查询效率可以建索引,但当每天更新数据时,又会重建索引,这是要耗费时间的。这时就需要综合考虑,甚至可以在更新前删除索引,更新后再重建。

    场景三,从上图中可以看到,因为在数据表里ID值都不相同,所以索引能发挥出比较大的作用。相反,如果某个字段重复率很高,如性别字段,或者某个字段大多数值是空(null),那么不建议对该字段建索引。

      请大家记住,一定是有业务需求了才会建索引。比如在一个商品表里,我们经常要根据name做查询,如果没有索引,查询速度会很慢,这时就需要建索引。但在项目开发中,如果不经常根据商品编号查询,那么就没必要对编号建索引。

    方法呢?

    ①语句一:select name from 商品表。不会用到索引,因为没有where语句。

    ②语句二:select * from 商品表 wherename=‘Java书’,会用到索引,如果项目里经常用到name来查询,且商品表的数据量很大,而name值的重复率又不高,那么建议建索引。

    ③语句三:select * from 商品表 where name like ‘Java%’这是个模糊查询,会用到索引,用like进行模糊查询时,如果第一个就是模糊的匹配符,比如where name like ‘%java’,那么在查询时不会走索引。在其他情况下,只要%不出现在第一个位置,那么都能用到索引。

      学生成绩表里有两个字段:姓名和成绩。现在对成绩这个整数类型的字段建索引。

    ①第一种情况,当数字型字段遇到非等值操作符时,无法用到索引。

    select name from 学生成绩表 where 成绩>95
    ,一旦出现大于符号,就不能用到索引,为了用到索引,我们应该改一下SQL语句里的where从句:

    where 成绩 in (96,97,98,99,100)
    ②第二种情况,如果对索引字段进行了某种左值操作,那么无法用到索引。

      能用到索引的写法:

    select name from 学生成绩表 where 成绩=60
      不能用到索引的写法:

    select name from 学生成绩表 where 成绩+40=100
    ③第三种情况,如果对索引字段进行了函数操作,那么无法用到索引。

      比如SQL语句:

    select * from 商品表 where substr(name)=‘J’
    我们希望查询商品名首字母是J的记录,可一旦针对name使用函数,即使name字段上有索引,也无法用到。

    (五)数据库优化问题
    (1)根据服务层面:配置mysql性能优化参数;

    (2)从系统层面增强mysql的性能:优化数据表结构、字段类型、字段索引、分表,分库、读写分离等等。

    (3)从数据库层面增强性能:优化SQL语句,合理使用字段索引。

    (4)从代码层面增强性能:使用缓存和NoSQL数据库方式存储,如MongoDB/Memcached/Redis来缓解高并发下数据库查询的压力。

    (5)减少数据库操作次数,尽量使用数据库访问驱动的批处理方法。

    (6)不常使用的数据迁移备份,避免每次都在海量数据中去检索。

    (7)提升数据库服务器硬件配置,或者搭建数据库集群。

    (8)编程手段防止SQL注入:使用JDBC PreparedStatement按位插入或查询;正则表达式过滤(非法字符串过滤);
    ————————————————
    版权声明:本文为CSDN博主「aogogogo」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/zhouboke/article/details/80414787

  • 相关阅读:
    【数据结构】堆栈
    【数据结构】线性表
    【算法】最大子列和问题
    【算法】复杂度的渐近表示
    【算法】什么是好的算法
    【算法】什么是算法
    【数据结构】什么是数据结构
    MySQL数据备份脚本
    二进制安装MySQL-5.7.28
    搭建zabbix+grafana监控
  • 原文地址:https://www.cnblogs.com/justuntil/p/12174437.html
Copyright © 2020-2023  润新知