zoukankan      html  css  js  c++  java
  • 关系型数据库索引设计与优化

    本文基于mysql innodb引擎

    请注意数据库DB2和MYSQL的聚簇索引和非聚簇索引的定义不同。

    1、三星索引:

    1、如果一个查询相关的索引行是相邻的,或者至少相距足够靠近,则索引可以被标记上第一颗星。(最小化了扫描的索引片的宽度)
    2、如果索引行的顺序与查询语句的需求一致,则索引可以被标记上第二颗星。(避免了排序操作)
    3、如果索引行包含查询语句中的所有列,则索引可以被标记第三颗星。(避免了回表)
    
    简单理解:
    1、where语句中的简单谓词和索引的顺序一致或相邻。
    2、order by的最终结果和索引结果集的顺序一致。 
    3、索引行包含所有查询字段。
    
    案例分析:假设cno为主键,所以二级索引(非聚簇索引)叶子页键值中,值包含了cno不需要建立cno列为索引
    select cno, fname from cust where lname between :lanme1 and :lname2 and city = :city order by fname

    建立索引从第三颗星到第一颗星。
    1、建立第三颗星(lname,city,fname)顺序不必在意,只需包含所有查询字段就可以。
    2、建立第二颗星。如果fname在lname之后,那么索引结果集的顺序和需要的顺序不一致(例:记录1的个别字段为lname=b,fname=b。记录2的个别字段为lname=a,fname=a。则索引集顺序为1,2,但需要的顺序是2,1),所以fname必须在lname之前3、建立第一颗星。找到简单谓词city。所以第一个索引一定为city,fname不能为第一个因为这样的话,不能使用索引(最左匹配)。但要想满足第一颗星必须city和lname字段相邻,以满足最小的索引片。但city已经是第一个,并且fname必须在lname之前,
    因此不能实现三星索引。那就只能在第一颗星和第二颗星之间做取舍。
    
    候选A:(city, lname, fname)舍弃第二颗星,实现最窄的索引片,但无序。
    1、取出等值谓词列,将这些列作为索引的最前列。(city)
    2、如果有范围谓词,将选择性最好的范围谓词作为索引的下一个列,其他范围谓词加入其后。 (city, lname)
    3、按照查询order by顺序添加order by(如果有desc,加上desc)列,忽略1.2步已添加的列。 (city, lname, fname)
    4、将查询语句中剩余列,加入索引之后(以不易变的列开始)。(city, lname, fname)
    
    候选B:(city, fname, lname)舍弃第一颗星,实现自排序,但索引片宽。 
    1、取出等值谓词列,将这些列作为索引的最前列。 (city)
    2、按照查询order by顺序添加order by(如果有desc,加上desc)列,忽略1.2步已添加的列。 (city, fname)
    3、将查询语句中剩余列,加入索引之后(以不易变的列开始)。 (city, fname, lname)
    具体使用A还是B,需要根据实际项目确定(一般第一颗星比第二颗星重要),或者bq
    /qube算法。

    2、索引设计与评估:

    个人理解:《数据库索引设计与优化》一书中,其案例中的索引存储结构类似于mysql的myisam,索引和数据分开存储。索引叶子页只保存数据在表中的指针。

    所以如果根据innodb的结构,就很难理解其第五章的qube案例。

    一旦一个新的查询语句出现,那么就要考虑现有的索引对新的语句来说是否合适。那么如何判断呢?步骤如下:

    对现有索引评估方法BQ:

    基本问题法bq:
    判断是否有一个已存在的索引包含了where子句中的所有列?
    1:如果没有,首先考虑将缺少的谓词列添加到一个已有的索引上。这将产生一个半宽索引2:如果还没有达到足够的性能,那么将所有涉及的列都添加到索引上(除主键外),以避免回表。这将产生一个宽索引3:如果还没有达到性能要求,那么就要设计一个新的索引。
    
    如何判断半宽索引宽索引的性能呢?
    1:使用测试库进行测试
    2:使用qube算法

    对索引的评估方法QUBE:

    快速上限估算法qube:
    qube假设所有表、索引都是以最理想的顺序组织的。结果为最差输入情况下的响应时间。 响应时间对比公式 LRT
    = TR * 10mx + TS * 0.01ms + F * 0.1ms 不同访问路劲对比公式 LRT = TR * 10mx + TS * 0.01ms LRT:本地响应时间 TR:随机访问的数量 TS:顺序访问的数量 F:有效fetch的数量

    案例分析:假设姓名不重复
    select cno, lname, fname, city from cust where lname = "张" and fname = ”飞"

    索引A(lname, fname)
    TR = 2(多一次回表), TS = 0, F = 1
    LRT = TR * 10ms + TS * 0.01ms + F * 0.1ms = 20.1ms
    索引B(lname, fname, city)最左匹配 TR = 1(覆盖索引), TS = 0, F = 1 
    LRT = TR * 10ms + TS * 0.01ms + F * 0.1ms = 10.1ms
    明显索引B更好。
  • 相关阅读:
    多表联合查询,利用 concat 模糊搜索
    order by 中利用 case when 排序
    Quartz.NET 3.0.7 + MySql 动态调度作业+动态切换版本+多作业引用同一程序集不同版本+持久化+集群(一)
    ASP.NET Core 2.2 基础知识(十八) 托管和部署 概述
    ASP.NET Core 2.2 基础知识(十七) SignalR 一个极其简陋的聊天室
    ASP.NET Core 2.2 基础知识(十六) SignalR 概述
    ASP.NET Core 2.2 基础知识(十五) Swagger
    ASP.NET Core 2.2 基础知识(十四) WebAPI Action返回类型(未完待续)
    linux磁盘管理 磁盘查看操作
    linux磁盘管理 文件挂载
  • 原文地址:https://www.cnblogs.com/unknown6248/p/14242610.html
Copyright © 2011-2022 走看看