索引

2018-09-06  本文已影响0人  杜大个

索引

1. 思考

在图书馆中是如何找到一本书的?

一般的应用系统对比数据库的读写比例在10:1左右(即有10次查询操作时有1次写的操作),

而且插入操作和更新操作很少出现性能问题,

遇到最多、最容易出问题还是一些复杂的查询操作,所以查询语句的优化显然是重中之重

2. 解决办法

当数据库中数据量很大时,查找数据会变得很慢

优化方案:索引

3. 索引是什么

索引是一种特殊的文件(InnoDB数据表上的索引是表空间的一个组成部分),它们包含着对数据表里所有记录的引用指针。

更通俗的说,数据库索引好比是一本书前面的目录,能加快数据库的查询速度

4. 索引目的

索引的目的在于提高查询效率,可以类比字典,如果要查“mysql”这个单词,我们肯定需要定位到m字母,然后从下往下找到y字母,再找到剩下的sql。如果没有索引,那么你可能需要把所有单词看一遍才能找到你想要的,如果我想找到m开头的单词呢?或者ze开头的单词呢?是不是觉得如果没有索引,这个事情根本无法完成?

5. 索引原理

除了词典,生活中随处可见索引的例子,如火车站的车次表、图书的目录等。它们的原理都是一样的,通过不断的缩小想要获得数据的范围来筛选出最终想要的结果,同时把随机的事件变成顺序的事件,也就是我们总是通过同一种查找方式来锁定数据。

数据库也是一样,但显然要复杂许多,因为不仅面临着等值查询,还有范围查询(>、<、between、in)、模糊查询(like)、并集查询(or)等等。数据库应该选择怎么样的方式来应对所有的问题呢?我们回想字典的例子,能不能把数据分成段,然后分段查询呢?最简单的如果1000条数据,1到100分成第一段,101到200分成第二段,201到300分成第三段……这样查第250条数据,只要找第三段就可以了,一下子去除了90%的无效数据。

7178f37egw1err37xke42j20hc08caax

作用

索引种类:

主键索引:   - 创建主键时就创建了主键索引

普通索引:
    - create index 索引名称 on 表名(列名,)
    - drop index 索引名称 on 表名
唯一索引:
    - create unique index 索引名称 on 表名(列名)
    - drop unique index 索引名称 on 表名

组合索引(最左前缀匹配):
    - create unique index 索引名称 on 表名(列名,列名)
    - drop unique index 索引名称 on 表名

    - create index ix_name_email on userinfo3(name,email,)
    - 最左前缀匹配
    组合索引效率 > 索引合并 
        组合索引:

        索引合并:

    名词:
        覆盖索引:
            - 在索引文件中直接获取数据

        索引合并:
            - 把多个单列索引合并使用

无索引:从前到后依次查找

索引:
    索引 => 创建额外文件(某种格式存储)
   create index 索引名称 on 表名(字段名);

索引种类(某种格式存储):

索引是在MYSQL的存储引擎层中实现的根据搜索引擎分类:

    B-Tree 索引:最常见的索引类型,大部分引擎都支持B树索引。
    HASH 索引:只有Memory引擎支持,使用场景简单。
    R-Tree 索引(空间索引):空间索引是MyISAM的一种特殊索引类型,主要用于地理空间数据类型。
    Full-text (全文索引):全文索引也是MyISAM的一种特殊索引类型,主要用于全文索引,InnoDB从MYSQL5.6版本提供对全文索引的支持。
    hash索引: 
        单值快
        范围(慢)
    btree索引: btree索引
        二叉树 (一种算法实现的)

6. 索引的使用

show index from 表名;

  1. 如果指定字段是字符串,需要指定长度,建议长度与定义字段时的长度一致
  2. 字段类型如果不是字符串,可以不填写长度部分

CREATE TABLE 表名 ( [...], INDEX 索引名 (列名1,列名 2,...) );

CREATE INDEX 索引名称 ON 表名(字段名称(长度))

DROP INDEX 索引名称 ON 表名;

7. 索引demo

7.1. 创建测试表testindex

create table test_index(title varchar(10));

7.2 使用python程序(ipython也可以)通过pymsql模块 向表中加入十万条数据

from pymysql import connect

def main():
    # 创建Connection连接
    conn = connect(host='localhost',port=3306,database='jing_dong',user='root',password='mysql',charset='utf8')
    # 获得Cursor对象
    cursor = conn.cursor()
    # 插入10万次数据
    for i in range(100000):
        cursor.execute("insert into test_index values('ha-%d')" % i)
    # 提交数据
    conn.commit()

if __name__ == "__main__":
    main()

7.3. 查询

set profiling=1;

select * from test_index where title='ha-99999';

show profiles;

create index title_index on test_index(title(10));

select * from test_index where title='ha-99999';

show profiles;

8. 注意:

要注意的是,建立太多的索引将会影响更新和插入的速度,因为它需要同样更新每个索引文件。对于一个经常需要更新和插入的表格,就没有必要为一个很少使用的where字句单独建立索引了,对于比较小的表,排序的开销不会很大,也没有必要建立另外的索引。 建立索引会占用磁盘空间

索引选择原则

  1. 较频繁的作为查询条件的字段应该创建索引
  2. 唯一性太差的字段不适合单独创建索引,即使频繁作为查询条件
  3. 更新非常频繁的字段不适合创建索引
  4. 不会出现在 WHERE 子句中的字段不该创建索引

性能优化过程中,选择在哪个列上创建索引是最非常重要的。可以考虑使用索引的主要有 两种类型的列:在where子句中出现的列,在join子句中出现的列,而不是在SELECT关键字后选择列表的列;

一般两种情况下不建议建索引: 表记录比较少,例如一两千条甚至只有几百条记录的表,没必要建索引,让查询做全表扫描就好了;

至于多少条记录才算多,这个个人有个人的看法,我个人的经验是以5000作为分界线,记录数不超过 5000可以考虑不建索引,超过5000条可以酌情考虑索引。

最后再次强调: 不要过度索引,只保持所需的索引。每个额外的索引都要占用额外的磁盘空间,并降低写操作的性能。 在修改表的内容时,索引必须进行更新,有时可能需要重构,因此,索引越多,所花的时间越长

总结一些其他注意事项: 其他注意事项

上一篇 下一篇

猜你喜欢

热点阅读