zoukankan      html  css  js  c++  java
  • 索引原理

    索引原理

    root 根节点
    branch 分支节点
    leaf 叶子节点

    1.b+树

    • 平衡树(btree-balance tree) 能够让查找某一个值经历的查找速度尽量平衡
    • 分支节点不存储数据 -- 让树的高度尽量矮,让查找一个数据的效率尽量的稳定
    • 在所有叶子结点之间加入了双向的地址链接 -- 查找范围非常快

    2.存储引擎的索引原理

    聚集索引(聚簇索引)

    • 全表数据都存储在叶子节点上 -- Innodb存储引擎中的主键

    非聚集索引(非聚簇索引)/辅助索引

    • 叶子节点不存放具体的整行数据,而是存储的这一行的主键的值

    1.Innodb

    聚集索引:只有存在于主键中(无需回表)
    辅助索引:除了主键之外所有的索引都是辅助索引(需要回表)
    回表: 只查询一个索引并不能解决查询中的问题,还需要到具体的表中去获取正行数据

    聚集索引与辅助索引的区别:

    叶子结点存放的是否是一整行的信息,聚集索引的叶子节点存放的是一整行信息,但是辅助索引在叶子节点不存放信息,存放索引,需要回到表中去获取数据。

    2.2MyIsam

    与innodb相同

    聚集索引:只有存在于主键中(无需回表)
    辅助索引:除了主键之外所有的索引都是辅助索引(需要回表)

    3.索引的种类

    ①priamry key 的创建自带索引效果---------非空 + 唯一 + 聚集索引
    ②unique 唯一约束的创建也自带索引效果-------唯一 + 辅助索引
    ③index 普通的索引--------------辅助索引

    4.创建与删除索引

    # 创建索引
        # create index ind_name on 表(name);
        create index ind_name on t1(name);
        
    #方法一:创建表时
          CREATE TABLE 表名 (
                    字段名1  数据类型 [完整性约束条件…],
                    字段名2  数据类型 [完整性约束条件…],
                    [UNIQUE | FULLTEXT | SPATIAL ]   INDEX | KEY
                    [索引名]  (字段名[(长度)]  [ASC |DESC]) 
                    );
    
    
    #方法二:CREATE在已存在的表上创建索引
            CREATE  [UNIQUE | FULLTEXT | SPATIAL ]  INDEX  索引名 
                         ON 表名 (字段名[(长度)]  [ASC |DESC]) ;
    
    
    #方法三:ALTER TABLE在已存在的表上创建索引
            ALTER TABLE 表名 ADD  [UNIQUE | FULLTEXT | SPATIAL ] INDEX
                                 索引名 (字段名[(长度)]  [ASC |DESC]) ;
                                 
    # 删除索引
        # drop index ind_name on 表;
        drop index ind_name on t1;
        
    普通索引INDEX:加速查找
    
    唯一索引:
        -主键索引PRIMARY KEY:加速查找+约束(不为空、不能重复)
        -唯一索引UNIQUE:加速查找+约束(不能重复)
    
    联合索引:
        -PRIMARY KEY(id,name):联合主键索引
        -UNIQUE(id,name):联合唯一索引
        -INDEX(id,name):联合普通索引
    

    5.索引的优缺点

    优点 : 查找速度快
    缺点 : 浪费空间,拖慢写的速度
    注:不要在程序中创建无用的索引

    6.索引无法命中的情况(重要***********)

    数据库使用的时候有什么注意事项

    # 从库的角度
    #         搭建集群
    #         读写分离
    #         分库
    # 建表的角度上
        # 1.合理安排表关系
        # 2.尽量把固定长度的字段放在前面
        # 3.尽量使用char代替varchar
        # 4.分表: 水平分,垂直分
    # 使用sql语句的时候
        # 1.尽量用where来约束数据范围到一个比较小的程度,比如说分页的时候
        # 2.尽量使用连表查询而不是子查询
        # 3.删除数据或者修改数据的时候尽量要用主键作为条件
        # 4.合理的创建和使用索引
            #创建索引
                # 1.选择区分度比较大的列
                # 2.尽量选择短的字段创建索引
                # 3.不要创建不必要的索引,及时删除不用的索引
            #使用索引
                # 1.查询的条件字段不是索引字段
                    # 对哪一个字段创建了索引,就用这个字段做条件查询
                # 2.在创建索引的时候应该对区分度比较大的列进行创建
                    # 1/10以下的重复率比较适合创建索引
                # 3.范围
                    # 范围越大越慢
                    # 范围越小越快
                    # like 'a%'  快
                    # like '%a'  慢
                # 4.条件列参与计算/使用函数
                # 5.and和or
                    # id name
                    # select * from s1 where id = 1800000 and name = 'eva';
                    # select count(*) from s1 where id = 1800000 or name = 'eva';
                    # 多个条件的组合,如果使用and连接
                        # 其中一列含有索引,都可以加快查找速度
                    # 如果使用or连接
                        # 必须所有的列都含有索引,才能加快查找速度
                # 6.联合索引 : 最左前缀原则(必须带着最左边的列做条件,从出现范围开始整条索引失效)
                        #create index mix_ind on 表 (id,name,email)
                    # (id,name,email)
                        #select * from 表 where id = 123; 命中索引
                        #select * from 表 where id > 123; 不命中索引
                        #select * from 表 where id = 123 and name = 'alex'; 命中索引
                        #select * from 表 where id > 123 and name = 'alex'; 不命中索引
                        #select * from 表 where id = 123 and email = 'alex@oldboy'; 命中索引
                        #select * from 表 where email = 'alex@oldboy'; 不命中索引,因为条件中没有id
                        #select * from 表 where name='alex' and email = 'alex@oldb
                # 7.条件中写出来的数据类型必须和定义的数据类型一致
                    # select * from biao where name = 666   # 不一致
                # 8.select的字段应该包含order by的字段
                    # select name,age from 表 order by age;  # 比较好   select 在前排序前获取了age字段后,再排序
                    # select name from 表 order by age;  # 比较差   select 在前排序前获取了name字段后,还得再排序一次
                
    其他注意事项:
    - 避免使用select *
    - 使用count(*)
    - 创建表时尽量使用 char 代替 varchar
    - 表的字段顺序固定长度的字段优先
    - 组合索引代替多个单列索引(由于mysql中每次只能使用一个索引,所以经常使用多个条件查询时更适合使用组合索引)
    - 尽量使用短索引
    - 使用连接(JOIN)来代替子查询(Sub-Queries)
    - 连表时注意条件类型需一致
    - 索引散列值(重复少)不适合建索引,例:性别不适合
    

    7.mysql 神器 explain

    查看sql语句的执行计划,以及是否命中了索引,命中的索引的类型

    例:

    explain select * from s1 where id < 1000000;
    

    8.覆盖索引与索引合并

    8.1覆盖索引

    索引合并和覆盖索引

    #联合索引
    	#(id,email)
    id = 100 and email like 'eva';
    
    #索引合并 : 分开创建在查询过程中临时合并成一条 Using union(ind_id,ind_email)
    		#创建索引的时候
    		create index ind_id on s1(id)
    		create index ind_email on s1(email)
    		select * from s1 where id = 100 or email  = 'eva100@oldboy'
    		临时把两个索引ind_id和ind_email合并成一个索引
    #覆盖索引:在查询过程中不需要回表   Using index
    		#对id字创建了索引
        select id from s1 where id =100     覆盖索引:在查找一条数据的时候,命中索引,不需要再回表
        select count(id) from s1 where id =100     覆盖索引:在查找一条数据的时候,命中索引,不需要再回表
        select max(id) from s1 where id =100     覆盖索引:在查找一条数据的时候,命中索引,不需要再回表
        select name from s1 where id =100   相对慢
        
       什么是mysql的执行计划?用过explain么?
    # 在执行sql语句之前,mysql进行的一个优化sql语句执行效率的分析(计划),可以看到有哪些索引,实际用到了那个索引,执行的type等级
        # id name email
        select * from s1 where id = 1000000 and name=eva and email = 'eva1000000@oldboy';
            # 有没有索引
            # 有几个
            # 用哪一个索引比较效率高
        explain select * from s1 where id = 1000000 and name=eva and email = 'eva1000000@oldboy';
    		
    

    9.慢日志

    慢日志能记录查询速度慢的sql语句

    慢日志是通过配置文件开启
    在mysql的配置中开启并设置一下
    在超过设定时间之后,这条sql总是会被记录下来
    这个时候我们可以对这些被记录的sql进行定期优化

    10.多表联查速度慢怎么办?

    慢查询优化 :
    首先从sql的角度优化
    把每一句话单独执行,找到效率低的表,优化这句sql
    了解业务场景,适当创建索引,帮助查询
    尽量用连表代替子查询
    确认命中索引的情况
    考虑修改表结构
    拆表
    把固定的字段往前调整
    使用执行计划,观察sql的type通过以上调整是否提高

    1.表结构
    尽量用固定长度的数据类型代替可变长数据类型,把固定长度的字段放在前面

    2.数据的角度上来说
    如果表中的数据越多 查询效率越慢
    列多 : 垂直分表
    行多 : 水平分表

    3.从sql的角度来说
    ①尽量把条件写的细致点儿,where条件多做筛选
    ②多表尽量连表代替子查询
    ③创建有效的索引,而规避无效的索引

    4.配置角度上来说
    开启慢日志查询 确认具体的有问题的sql

    5.数据库
    读写分离,解决数据库读的瓶颈

    11.数据表库的导入导出

    # 打开cmd输入一下命令
    # 备份表 :homwork库中的所有表和数据
    mysqldump -uroot -p123 homework > D:s23day42a.sql
    # 备份单表
    mysqldump -uroot -p123 homework course > D:s23day42a.sql
    # 备份库 :
    mysqldump -uroot -p123 --databases homework > D:s23day42db.sql
    
    # 恢复数据:
    # 进入mysql 切换到要恢复数据的库下面
    sourse D:s23day42a.sql
    

    12.开启事务,给数据加锁

    begin;
    select id from t1 where name = 'alex' for update;
    update t1 set id = 2 where name = 'alex';
    commit;
    

    13.sql注入

    SQL注入攻击指的是通过构建特殊的输入作为参数传入Web应用程序,
    而这些输入大都是SQL语法里的一些组合,
    通过执行SQL语句进而执行攻击者所要的操作,
    其主要原因是程序没有细致地过滤用户输入的数据,致使非法数据侵入系统。

    import pymysql
    
    conn = pymysql.connect(host='127.0.0.1', user='eva', password="123",
                     database='db2')
    cur = conn.cursor()
    user = "'akhksh' or 1=1 ;-- "# 使用特殊语法使sql语句必查询成功
    password = '*******'
    sql = "select * from user where user_name = %s and password =%s;"% (user,password)
    print(sql)
    cur.execute(sql)
    ret = cur.fetchone()
    print(ret)
    cur.close()
    conn.close()
    
  • 相关阅读:
    C语言寒假大作战04
    C语言寒假大作战03
    C语言寒假大作战02
    C语言寒假大作战01
    C语言I作业12—学期总结
    C语言I作业11
    C语言I作业10
    C语言I作业09
    C语言I作业08
    C语言寒假大作战04
  • 原文地址:https://www.cnblogs.com/zheng0907/p/12743122.html
Copyright © 2011-2022 走看看