之前遇到一个问题(因为最近又遇到了,所以记录下来),表字段加了索引但是查询依然很慢,大概的情况如下

问题描述:

有个表T_ORDER(匿名),字段若干,其中有个TX_TIME交易时间,MERCHANT_NO商户号都已经添加了索引,表数据量较大5000W+

SQL大致如下(实际SQL比下面的复杂一点点,会做 LEFT JOIN 其他表,但是不多):

SELECT * FROM T_ORDER
WHERE
CUSTOMER_NO = #{customerNo}
AND TX_TIME BETWEEN #{startTxTime} AND #{endTxTime}

查询一天某商户的数据经常超时(好几秒,具体的忘了)。

问题排查:

1、首先通过DEBUG日志将打印出来的SQL与参数拼写成完整SQL在数据库执行,发现很快(几十毫秒),并不是SQL本身问题(其实SQL本身也有一定的问题,比如表数据太大,又进行LEFT JOIN ,但因其不是这次分析重点,就此忽略)。

2、mybatis的#会将SQL参数化,而在步骤1中的SQL是具体参数的,非参数化的, 所以怀疑参数化的SQL与非参数化的SQL执行计划不一样,于是找了DBA去帮忙查两SQL的执行计划(因为本人不擅长数据库方面的东西,并且身边有资深DBA,所以就直接请教他们了),果然不一样。

3、于是将mybatis中该SQL的#全部替换为了$,部署发现问题解决了,之前部分SQL慢的问题未出现了。

问题分析:

1、首先说明一下,mybatis中的#与$差别,#{}的参数是参数化的,也就是在SQL中是?替代的;${}的参数是拼接的,也就是在SQL中直接拼接上了参数的值,所以在替换成$后,SQL就与直接在数据库执行的一致了。

2、为啥会变快呢?在DBA的协助下,发现参数化的SQL在数据库的编译会存在一个问题,就是编译SQL的时候,会依据当前全表的量基于一定的算法生成执行计划,然后将执行计划缓存起来;而拼接好的SQL则会基于当前拼接的多个参数实际筛选的量基于算法生成执行计划,然后缓存起来。也就是说第二种的执行计划是动态的,每次有可能不一样,都是最优的。(具体的执行计划生成算法不是很清楚,也不是这里的重点)

举个例子:T_ORDER中,A商户每天可产生2500W数据,而剩下2500W条交易分别数据2500W个商户的,每个商户一条。若参数化,那么执行计划可能是,执行计划1,优先走时间索引,再走商户索引(或者是执行计划2优先走商户索引,再走时间索引,只能是两者的其中一个,然后缓存下来,以后都走这个缓存的)。若执行计划1,那么查询A商户一天的交易就比较快,查询剩余某个商户就比较慢若执行计划2,那么查询A商户就比较慢,查询剩余某个商户的就比较快总会有不好的地方若拼接的话,那么情况就会变了查询A商户一天交易的时候,执行计划就会是 优先走时间索引,再走商户索引查询剩余某个商户一天交易的时候,执行计划就会是 优先走商户索引,再走时间索引

结论:

1、mybatis中,高频简单的SQL,参数化#会更好(因为编译耗时占用SQL执行耗时比例很大,几十倍吧),大表复杂SQL可以尝试使用$拼接,会快很多(编译耗时占用SQL执行耗时的比例很小,每次编译也就无所谓了,但可以使执行计划更准确,但是小心SQL注入)

2、数据库上有个绑定变量窥视的设置,打开后用#就跟用$的执行计划一致了,这块参考了别人的文章(为什么预估执行计划与真实执行计划会有差异?_数据和云的博客-CSDN博客)

3、参数隐式转化也影响索引生效,具体可以看这篇,执行计划的东西可以学习一下(为什么预估执行计划与真实执行计划会有差异?_数据和云的博客-CSDN博客)

最近看了这篇文章,很有帮助

基于代价的慢查询优化建议 - 美团技术团队对于数据库来说,慢查询往往意味着风险。SQL执行得越慢,消耗的CPU资源或IO资源也会越大。大量的慢查询可直接引发业务故障,关注慢查询即是关注故障本身。本文主要介绍了美团如何利用数据库的代价优化器来优化慢查询,并给出索引建议,评估跟踪建议质量,运营治理慢查询。https://tech.meituan.com/2022/04/21/slow-query-optimized-advice-driven-by-cost-model.html

表字段加了索引但是查询依然很慢相关推荐

  1. 面试官:为啥加了索引查询会变快?

    面试官:你在工作中有遇到SQL查询比较慢的情况吗? 果子:有的.随着业务的发展,表中的数据量会越来越大,查询就会越来越慢 面试官:那你是如何优化查询慢的问题? 果子:在需要查询的列上加索引 面试官:那 ...

  2. 【MySQL】明明加了索引,为何不生效?

    加了索引却不生效可能会有以下几种原因. 1. 索引列是表示式的一部分,或是函数的一部分 如下SQL: SELECT book_id FROM BOOK WHERE book_id +1 = 5; 或者 ...

  3. Oracle查询表名注释及表字段注释

    Oracle查询表名注释及表字段注释 系统视图-ALL_COL_COMMENTS ALL_COL_COMMENTS视图存储当前用户可访问的表中字段的注释信息. 名称 类型 描述 column_name ...

  4. sql 两个表字段不一样合并查询_数据分析进阶--SQL多表查询

    下午写完了上一篇文章,晚上就开始做牛客的SQL题啦,然后发现少少的十题就用到了好几次多表连接,case在实际分析过程中也非常常用,所以我打算单独把多表查询和case拉出来写一篇文章. 文章目录: 表的 ...

  5. mysql加索引后查询时间变长了(终于有头绪了)

    在使用ip查询的地址(地址和ip对应的信息存在mysql中,使用的是myisam)的过程中遇到一个这样的问题: 给表中的一些字段加索引后查询时间变长了,cpu飙升了 该表的结构如下 这是什么原因呢难道 ...

  6. laravel 同数据表字段比较查询和状态不正规排序

    今天写群组推荐接口,要求未满的群 ( 群最大人数字段maxusers, 群人数字段affiliations_count 都在群组表中),官方,热门(普通群0 ,官方1,热门2 ) 排序的群 同表字段比 ...

  7. SQL Server2019数据库查询所有数据库名、表名、表结构、表字段、主键方法演示,执行sql提示对象名‘user_tab_columns‘、 ‘user_cons_columns‘ 无效问题解决

    SQL Server2019 数据库查询所有数据库名.表名.表结构.表字段.主键方法演示 第一章:查询方法 ① 查询所有数据库名 ② 查询所有表名方法 ③ 查询表结构.表字段方法 ④ 查询主键方法 第 ...

  8. mysql查询表字段是否存在_Mysql判断表字段或索引是否存在

    判断字段是否存在: DROP PROCEDURE IF EXISTS schema_change; DELIMITER // CREATE PROCEDURE schema_change() BEGI ...

  9. mysql数据库的注释语句是_coding++ :MySQL 使用 SQL 语句查询数据库所有表注释已经表字段注释...

    1.要查询数据库 "mammothcode" 下所有表名以及表注释 /*查询数据库 'mammothcode' 所有表注释*/SELECT TABLE_NAME,TABLE_COM ...

最新文章

  1. python现在最新的版本-Python 3.8 已发布,现在是切换至新版本的好时机吗?
  2. 2015 提高组 跳石头--二分答案
  3. SAP UI5 Web Component React应用如何在Component之间跳转
  4. thinkpad s3 安装win8 kali双系统笔记
  5. php怎样实现表格自动缩放字体,php实现在限定区域里自动调整字体大小的类实例,字体大小实例_PHP教程...
  6. 在要求或期待别人做到某事的时候,先反思下自己是否值得。就好比我常会期望有很多人会记住我生日是哪天,但......
  7. python 合并与连接
  8. Centos7 Kubernetes(k8s) 开发服务器(单服务器)部署 mariadb/mysql 数据库
  9. linux中ps-p,linux下ps命令
  10. fp5139应用电路图_LM358各种应用电路
  11. 【数学建模】2 TOPSIS优劣解距离法
  12. P2P网络NAT穿透原理(打洞方案)
  13. [渝粤教育] 西南科技大学 管理学原理 在线考试复习资料(2)
  14. 传统行业+互联网思维
  15. 怎么将微博图片中的水印去掉
  16. 2019 Revit二次开发企业
  17. 2023前端求职经历回顾及面试题总结
  18. Vue入门教程 第五篇 (组件)
  19. 七天玩转Redis | Day7、Redis常见面试题及课程总结
  20. 【经典密码学】Rot5/Rot13/Rot18/Rot47----python

热门文章

  1. Arduino Nano 驱动OLED滚动显示
  2. php 银联支付(快捷支付)
  3. php实现在线抽题,PHP实现类似题库抽题效果
  4. 边缘计算架构、分层及典型组网拓扑
  5. 上手基金,看这一篇就够了
  6. 计算机二级黑板板书书写,清华老师的板书惊艳朋友圈 8个技巧让黑板亮起来
  7. Fixturlaser对中仪维修GO/NXA Pro系列
  8. android l 论坛,同步更新魔趣源码Android-L编译
  9. qdbus模块_PyQt 学习笔记4——库结构
  10. [Ubuntu20.04] 没有eth0只有lo和wlo1(没有网卡驱动)