zoukankan      html  css  js  c++  java
  • 数据库索引之优化查询速度

    (一)索引的作用
    索引通俗来讲就相当于书的目录,当我们根据条件查询的时候,没有索引,便需要全表扫描,数据量少还可以,一旦数据量超过百万甚至千万,一条查询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

  • 相关阅读:
    leetcode 268. Missing Number
    DBSCAN
    python二维数组初始化
    leetcode 661. Image Smoother
    leetcode 599. Minimum Index Sum of Two Lists
    Python中的sort() key含义
    leetcode 447. Number of Boomerangs
    leetcode 697. Degree of an Array
    滴滴快车奖励政策,高峰奖励,翻倍奖励,按成交率,指派单数分级(1月3日)
    北京Uber优步司机奖励政策(1月2日)
  • 原文地址:https://www.cnblogs.com/justuntil/p/12174437.html
Copyright © 2011-2022 走看看