• 22 mysql range 查询


    前言
    这里主要是 探究一下 explain $sql 中各个 type 

    诸如 const, ref, range, index, all 的查询的影响, 以及一个初步的效率的判断 

    这里会调试源码来看一下 各个类型的查询 需要 lookUp 的记录 

    以及 相关的差异 

    此系列文章建议从 mysql const 查询 开始看

     

    测试表结构信息如下 

    1. CREATE TABLE `tz_test` (
    2. `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
    3. `field1` varchar(12) DEFAULT NULL,
    4. PRIMARY KEY (`id`) USING BTREE
    5. ) ENGINE=InnoDB AUTO_INCREMENT=3333343 DEFAULT CHARSET=utf8

     

    测试数据为序列 1 – 99

    6b59f9ee880d4ca4915255d2f0d52dfb.png

     

     

    range 查询存在的记录

    执行查询如下 “select * from tz_test where field1 > 'field33' and field1 < 'field37';”

     

    optimize 的时候, 根据索引定位了 ”field33” 和 “field37” 的位置 

    dac2dcf8fd2e4a5ea7e51244f752e8f3.png

     

    第一次查询是从索引 ‘field34’ -> 34 开始, 然后 row_search_idx_cond_check 来判断当前记录是否满足条件 

    比较的方式是当前记录的给定的字段 是否属于给定的区间, 因为是顺序往下遍历, 只需要判断是否超出了 右边界 即可

    7353b8cdc54d42e69b85d9c1a015d2bf.png

     

    这里是将 rec 转换为 mysql_rec 的地方

    bc30eac8c3b6445ab950ed46cf4b81d4.png 

    这里根据索引的区间判断是没有使用到 prebuilt->fetch_cache 的 

    然后在迭代的过程中会依次比较 “field36”-> 36, “field37”->37 的记录信息, id 为 35 的记录 field1 为 “field33”, 索引是按照顺序排列的, 因此是不会遍历到索引 “field33” -> 35 -

    迭代到 “field36” -> 36 的时候满足条件, 因此获取给定的记录返回回去

    迭代到 “field37” -> 37 的时候, 一边是索引记录的值 “field37”, 另外一边是查询条件中的 “field37”

    然后这里比较 两者相等, 外面根据查询条件是否包含 “等于”, 来更新这里的比较结果 

    来符合我们的一个 “<”/”<=” 的一个计算需求 

    941f3aa5ead0464d9edfca0dcb589201.png

     

    我们这里查询条件为 “field1 < 'field37';”, 因此在 “field37” = “field37” 的场景下面是不满足需求的, 因此这里设置了一个 如果两者相等的时候的一个默认值, 这里为 1 表示 OUT_OF_RANGE

    key_compare_result_on_equal 是在之前设置的, 根据查询条件动态调整 

    b883a3c8578b46e0a2ee2723073226f1.png

     

    然后外层 row_search_mvcc 控制着外层跳出循环 

    2df2be13a21a4f8c8beeb316d3bfee12.png 

    然后外层 sub_select 跳出循环 

    d48298aeb8024a988204de7191bf8f6b.png 

     

    range 使用索引 or 不使用索引 ?

    假设执行查询如下 “select * from tz_test where field1 > 'field33';”

    这里比较的两个 estimate, 一个应该是 全表扫描 的开销, 另外一个是使用 field1 索引的开销 

    cost 的 io_cost 为扫描的记录数量, cpu_cost 为计算的 cpu 开销 

    allTableEstimate 的计算方式不太清楚, 这里合计为 23[每次计算可能有所差异, 我们这里仅仅以这次调试为例], 所以 可以推导出的是如果 range 查询记录数量超过了 23 是肯定使用 全表扫描 

    7f917f51f58346fd8e7b6f8fc3a55589.png

     

    假设执行查询如下 “select * from tz_test where field1 > 'field97';”

    这里很显然就会使用 field1 字段的 range 查询 

    3cbe418f714a4bacb4fd27216007fb3e.png

     

    假设执行查询如下 “select * from tz_test where field1 > 'field81';”

    选择全表扫描 

    91a332a65eae4779a16ae0a802d5d52e.png

     

    假设执行查询如下 “select * from tz_test where field1 > 'field82';”

    选择索引查询 

    8c37fe47d6cd4c63b3d6ae9c3f4953aa.png

     

     

     

      

     

  • 相关阅读:
    【定制项目】【M15 消防安全宣传】【横屏版】主要模块:视频 + 音频 + 图标 + 问答游戏
    .net 写了一个支持重试、熔断和超时策略的 HttpClient 实例池
    5800计算程序
    Rasa系列教程(一) -- 系统及各组件介绍
    同花顺l2数据接口的委托队列是什么?
    CSS从入门到精通(4)
    MapReduce核心原理(下)
    nginx
    2023最新最全【Adobe After Effection 2023】下载安装零基础教程【附安装包】
    将VMProtect集成到应用程序教程之实模式(三):测试结果
  • 原文地址:https://blog.csdn.net/u011039332/article/details/131135198