zoukankan      html  css  js  c++  java
  • mysql基础(四)之索引

    索引简介:

    1、普通索引
    
      普通索引(由关键字KEY或INDEX定义的索引)的唯一任务是加快对数据的访问速度。因此,应该只为那些最经常出现在查询条件 (WHEREcolumn=)或排序条件(ORDERBYcolumn)中的数据列创建索引。只要有可能,就应该选择一个数据最整齐、最紧凑的数据列(如 一个整数类型的数据列)来创建索引。
    
      2、唯一索引
    
      普通索引允许被索引的数据列包含重复的值。比如说,因为人有可能同名,所以同一个姓名在同一个“员工个人资料”数据表里可能出现两次或更多次。
    
      如果能确定某个数据列将只包含彼此各不相同的值,在为这个数据列创建索引的时候就应该用关键字UNIQUE把它定义为一个唯一索引。这么做的好 处:一是简化了MySQL对这个索引的管理工作,这个索引也因此而变得更有效率;二是MySQL会在有新记录插入数据表时,自动检查新记录的这个字段的值
        是否已经在某个记录的这个字段里出现过了;如果是,MySQL将拒绝插入那条新记录。也就是说,唯一索引可以保证数据记录的唯一性。
         事实上,在许多场合, 人们创建唯一索引的目的往往不是为了提高访问速度,而只是为了避免数据出现重复。
    
      3、主索引
    
      在前面已经反复多次强调过:必须为主键字段创建一个索引,这个索引就是所谓的“主索引”。主索引与唯一索引的唯一区别是:前者在定义时使用的关键字是PRIMARY而不是UNIQUE。
    
      4、外键索引
    
      如果为某个外键字段定义了一个外键约束条件,MySQL就会定义一个内部索引来帮助自己以最有效率的方式去管理和使用外键约束条件。
    
      5、复合索引
    
      索引可以覆盖多个数据列,如像INDEX(columnA,columnB)索引。这种索引的特点是MySQL可以有选择地使用一个这样的索 引。如果查询操作只需要用到columnA数据列上的一个索引,就可以使用复合索引INDEX(columnA,columnB)。不过,这种用法仅适用 于在复合索引中排列在前的数据列组合。比如说,INDEX(A,B,C)可以当做A或(A,B)的索引来使用,但不能当做B、C或(B,C)的索引来使 用。
    
      6、索引的长度
    
      在为CHAR和VARCHAR类型的数据列定义索引时,可以把索引的长度限制为一个给定的字符个数(这个数字必须小于这个字段所允许的最大字符 个数)。这么做的好处是可以生成一个尺寸比较小、检索速度却比较快的索引文件。
        在绝大多数应用里,数据库中的字符串数据大都以各种各样的名字为主,把索引 的长度设置为10~15个字符已经足以把搜索范围缩小到很少的几条数据记录了。
        在为BLOB和TEXT类型的数据列创建索引时,必须对索引的长度做出限 制;MySQL所允许的最大索引全文索引文本字段上的普通索引只能加快对出现在字段内容最前面的字符串(也就是字段内容开头的字符)进行检索操作。
        如果字 段里存放的是由几个、甚至是多个单词构成的较大段文字,普通索引就没什么作用了。这种检索往往以的形式出现,这对MySQL来说很复杂,如果需要处理的数 据量很大,响应时间就会很长。
    
      这类场合正是全文索引(full-textindex)可以大显身手的地方。在生成这种类型的索引时,MySQL将把在文本中出现的所有单词创 建为一份清单,查询操作将根据这份清单去检索有关的数据记录。全文索引即可以随数据表一同创建,也可以等日后有必要时再使用下面这条命令添加:
    
      ALTERTABLEtablenameADDFULLTEXT(column1,column2)有了全文索引,就可以用SELECT查询命令去检索那些包含着一个或多个给定单词的数据记录了。下面是这类查询命令的基本语法:
    
      SELECT*FROMtablename
    
      WHEREMATCH(column1,column2)AGAINST(‘word1','word2','word3’)
    
      上面这条命令将把column1和column2字段里有word1、word2和word3的数据记录全部查询出来。
    View Code
    参考博客: http://www.cnblogs.com/wupeiqi/articles/5716963.html

    索引是表的目录,在查找内容之前可以先在目录中查找索引位置,以此快速定位查询数据。对于索引,会保存在额外的文件中。

    索引: 作用: 加速查找 约束
    1 普通索引 仅加速查询
    2 主键索引 加速查询 + 列值唯一 + 表中只有一个(不可以有null)
    3 唯一索引 加速查询 + 列值唯一(可以有null)
    create table t1(
    id int ....,
    num int,
    xx int,
    unique 唯一索引名称 (列名,列名),
    constraint ....
    )
    作用:加速查找
    不能重复 可以为空 可以设置多行为唯一索引(联合唯一)
    ps 主键不能为空
    4 联合索引:(多列)
    联合唯一索引
    联合主键索引
    联合普通索引
    5 全文索引:对文本的内容进行分词,进行搜索


    无索引:从数据库中从前往后依次查找
    有索引:创建额外的文件,以某种格式存储
    索引种类: hash 无序 单值查找快 范围查找慢
    btree 数据结构: 二叉树
    30

    10 40

    5 15 35 66

    1 6 11 19 21 39 55 100

    相关命令: desc t1 查看表结构
    show create table t1G 显示创建表时的sql语句 将表格90度旋转
    show index from t1 查看索引
    explain sql语句 查看预估的执行时间

    set profiling = 1; 查看执行时间
    SQL...
    show profiles;
    建立索引:
    a 额外的文件保存特殊的数据结构
    b 查询快 插入更新删除慢
    c 命中索引
    select * from t1 where email='fejfef'
    select * from t1 where email like 'fdjafh'; 慢
    创建普通索引:
    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,)
    最左前缀匹配
    select * from userinfo3 where name='alex'; 匹配
    select * from userinfo3 where name='alex' and email='asdf'; 匹配

    select * from userinfo3 where email='alex@qq.com'; 不匹配,不会按照索引查找


    覆盖索引: 只是一种行为
    直接在索引文件中就可以找到的数据
    索引合并: 只是一种行为
    把多个单列索引合并使用

    组合索引效率 > 索引合并效率
    组合索引
    - (name,email,) 适用于经常使用联合查找的情况
    select * from userinfo3 where name='alex' and email='asdf';
    select * from userinfo3 where name='alex';
    索引合并:
    - name
    - email
    select * from userinfo3 where name='alex' and email='asdf';
    select * from userinfo3 where name='alex';
    select * from userinfo3 where email='alex';


    正确使用索引
    1 like
    select * from t1 where email='fejfef'
    select * from t1 where email like 'fdjafh'; 慢
    2 函数
    count(1)或count(列) 代替 count(*)
    select * from tb1 where reverse(name) = 'wupeiqi';
    3 or
    nid 建立索引而email没有建立索引---------不会按照索引查找
    select * from tb1 where nid = 1 or email = 'seven@live.com';

    nid建立索引,email没有建立索引,name也建立索引,-----会按照索引查找
    select * from tb1 where nid = 1 or email = 'seven@live.com' and name = 'alex'
    4 类型不一致
    如果列是字符串类型,传入条件是必须用引号引起来
    select * from tb1 where name = 999; 不会走索引
    select * from tb1 where name = '999'; 会走索引
    5 !=
    select * from tb1 where name != 'alex'
    特别的:如果是主键,则还是会走索引
    select * from tb1 where nid != 123
    6 - >
    select * from tb1 where name > 'alex'
    特别的:如果是主键或索引是整数类型,则还是会走索引
    select * from tb1 where nid > 123
    select * from tb1 where num > 123
    7 order by
    当根据索引排序时候,选择的映射如果不是索引,则不走索引
    特别的:如果对主键排序,则还是走索引:
    select * from tb1 order by nid desc;
    8 组合索引最左前缀

    其他注意事项
    避免使用 select *
    count(1)或count(列) 代替count(*)
    创建表时尽量用char代替varchar
    表的字段顺序按照固定长度的字段优先
    组合索引代替多个单列索引(经常使用多个条件查询时)
    尽量使用短索引 create index xxxx on userinfo(username(3)) 对username的前3个字符建立索引
    连表时注意条件类型需一致
    索引散列值不适合建索引
    limit 分页
    1 select * from userinfo4 limit 20,10
    2 select * from userinfo3 where id in(select id from userinfo3 limit 200000,10)
    3 方案:记录当前页最大或最小ID
    1 页面只有上一页和下一页
    下一页:select * from userinfo3 where id > max_id limit 10;
    下一页:select * from userinfo3 where id < min_id order by id desc limit 10;
    2 上一页 192 193 [196] 197 198 199 下一页
    select * from userinfo4 where id in(
    select id from (select id from userinfo4 where id > max_id limit 30) as N order by N.id desc limit 10)
    4 select * from userinfo4 where id between 1 in 10 错误,因为id不连续,无法使用范围查找


    查询时间:explain + 查询SQL - 用于显示SQL执行信息参数,根据参考信息可以进行SQL优化
    执行计划:让mysql预估执行操作所需要的时间(一般正确)

    all < index < range <index_merge < ref_or_null < ref <eq_ref <system/const
    慢:select * from userinfo3 where name='alex'

    explain select * from userinfo3 where name='alex'
    type : all(全表扫描)
    select * from userinfo3 limit 1; (特殊情况)
    快:
    select * from userinfo3 where email='alex'
    type:const(走索引)


    DBA工作:
    慢日志:--执行时间
    --未命中索引
    --日志文件路径
    配置:
    --内存
    show variables like '%query%'
    set global 变量名 = 值
    --配置文件
    slow_query_log = OFF 是否开启慢日志记录
    long_query_time = 2 时间限制,超过此时间,则记录
    slow_query_log_file = /usr/slow.log 日志文件
    log_queries_not_using_indexes = OFF 为使用索引的搜索是否记录

    修改:
    1 mysqld--default-file='F:mysql-5.7.16-winx64my-default.ini'

    2 my.conf内容:
    slow_query_log=ON
    slow_query_log_file='........'
    注意:修改配置文件之后,需要重启服务

    --查看慢日志:
    mysqldumpslow -s at -a /usr/slow.log
    -s ORDER 排序方式
    what to sort by (al, at, ar, c, l, r, t), 'at' is default
    al: average lock time
    ar: average rows sent
    at: average query time
    c: count
    l: lock time
    r: rows sent
    t: query time
    -a 不要将SQL中数字转换成N,字符串转换成S。don't abstract all numbers to N and strings to 'S'
  • 相关阅读:
    【设计模式】模板模式
    【设计模式】策略模式
    【设计模式】空对象模式
    【设计模式】状态模式
    【设计模式】观察者模式
    【设计模式】备忘录模式
    【设计模式】中介者模式
    【设计模式】迭代器模式
    【设计模式】解释器模式
    【设计模式】命令模式
  • 原文地址:https://www.cnblogs.com/liuguniang/p/7044345.html
Copyright © 2011-2022 走看看