mysql in优化_MySQL的一次优化记录 (IN子查询和索引优化)
这两天实习项目遇到一个网页加载巨慢的问题(10多秒),然后定位到是一个MySQL查询特别慢的语句引起的:
SELECT *
FROM (
SELECT DISTINCT t.vc_date, t.c_bankno, t.vc_bankacco, t.vc_moneytype, t.en_totalbala
, t.en_usablebala, t1.vc_nameinbank, date_format(t.D_IMPORTTIME, '%Y-%m-%d %H:%i:%S') AS D_IMPORTTIME
, t.vc_fundcode, t.c_datamode, t.vc_taskid, t.id, t.vc_projectname
, t.vc_projectcode, t1.c_accotype
, (
SELECT IF(vc_occurtime IS NULL, DATE_FORMAT(vc_occurdate, '%Y-%m-%d'), DATE_FORMAT(CONCAT(vc_occurdate, vc_occurtime), '%Y-%m-%d %H:%i:%S')) AS tradeTime
FROM tbanktradedetail_view
WHERE vc_bankacco = t.vc_bankacco
) AS d_tradetime, t3.vc_entry_caption AS C_ACCOTYPE_STR, t5.vc_entry_caption AS VC_BANKNAME, t4.vc_entry_caption AS VC_MONEYTYPE_STR
FROM tbankaccobala t
INNER JOIN tbankaccoinfo t1 ON t.vc_bankacco = t1.vc_bankacco
INNER JOIN (
SELECT vc_entry_value, vc_entry_caption
FROM ot_dic_tdictionaryentry
WHERE vc_entry_no = '5087'
) t3
ON t1.c_accotype = t3.vc_entry_value
INNER JOIN (
SELECT vc_entry_value, vc_entry_caption
FROM ot_dic_tdictionaryentry
WHERE vc_entry_no = '1004'
) t4
ON t1.VC_MONEYTYPE = t4.vc_entry_value
INNER JOIN (
SELECT vc_entry_value, vc_entry_caption
FROM ot_dic_tdictionaryentry
WHERE vc_entry_no = '1014'
) t5
ON t.c_bankno = t5.vc_entry_value
WHERE 1 = 1
AND t.id IN (
-- this query will take 4.6s:
-- SELECT SUBSTRING_INDEX(GROUP_CONCAT(id ORDER BY d_importtime DESC), ',', 1)
-- FROM tbankaccobala
-- GROUP BY vc_bankacco
-- but the following query only takes 1.1s:
SELECT hhhh from(
SELECT SUBSTRING_INDEX(GROUP_CONCAT(id ORDER BY d_importtime DESC), ',', 1) as hhhh
FROM tbankaccobala
GROUP BY vc_bankacco
) as sbstr
-- 对IN的子查询做二次查询
)
) t
WHERE 1 = 1
ORDER BY t.D_IMPORTTIME DESC
抽出查询慢关键部分:
SELECT *
FROM (
SELECT DISTINCT t.vc_date, t.c_bankno, t.vc_bankacco, t.vc_moneytype, t.en_totalbala
-- 此处省略选择多个列语句
FROM tbankaccobala t
-- 此处省略多张表连表查询语句
WHERE 1 = 1
AND t.id IN (
-- 这个查询需要3s:
SELECT SUBSTRING_INDEX(GROUP_CONCAT(id ORDER BY d_importtime DESC), ',', 1)
FROM tbankaccobala
GROUP BY vc_bankacco
)
) t
这个语句导致前端页面10多秒才有响应(但MySQL执行显示要4.6秒,phpMyAdmin也是10秒左右响应,为何?)
IN子查询语句优化
把IN语句里面的内容改成下面这样,只在外层再加一个select,就把3s的查询缩短为0.006s:
SELECT hhhh from(
SELECT SUBSTRING_INDEX(GROUP_CONCAT(id ORDER BY d_importtime DESC), ',', 1) as hhhh
FROM tbankaccobala
GROUP BY vc_bankacco
) as sbstr
-- 对IN的子查询做二次select,或者把IN改为JOIN都可以解决速度奇慢的问题
原语句空行处省略了一系列的其他表和 INNER JOIN 语句。一开始怀疑是多表的JOIN操作导致速度变慢,但删去JOIN变成上面这段注释掉的语句之后,速度依然非常慢,显示要3s,于是猜测 IN 才是导致速度变慢的主要因素,改后只要0.006s,啧…
EXPLAIN 未优化的语句:
(相关子查询是使用外部查询中的值的子查询)
EXPLAIN 优化的语句:
我的理解:优化前,子查询是相关子查询,对于外部产生的每个值,都要执行一次子查询;优化后,子查询不再是相关子查询,只需要执行一次子查询并缓存中间结果,外部查到的每个值去缓存的中间结果里比对一下就行了。
(有人说是能不能用索引的原因——这么说应该是不对的)
完整查询的后端响应速度对比:
前:
后:
索引优化
对于这么小的数据规模,时间还是太长了… 看前面explain执行计划的截图,嗯,没有索引…
给t1的vc_bankacco加上索引之后
解释执行计划:
查询和网页响应用时大幅缩短:
再看sql里还有三个join:
用的都是ot_dic_tdictionaryentry这张表的t4.vc_entry_value字段,那么试着给这个字段也加上索引吧,然后用时如下:
是的,时间反而变长了!
explain执行计划:
所以变慢原因是:
没加vc_entry_value的索引时,会先用vc_entry_no选出一个数量很小的表,再和t1做join,
而加了vc_entry_value的索引之后,MySQL就把这个索引用了起来,join语句被优化为先FirstMatch(ot_dic_tdictionaryentry),这产生了一个1713*1713=2934369行的中间结果(笛卡尔乘积),然后才使用vc_entry_no进行where过滤。
所以索引不能乱加啊,加错了反而会导致性能下降!这个示例里的查询要加索引只能在vc_entry_no上索引,而不能在vc_entry_value上!
这个示例中主要提升是IN子查询语句的优化。在使用索引的情况下,对IN子查询做优化前后的查询时间分别是3.1s和0.16s
mysql in优化_MySQL的一次优化记录 (IN子查询和索引优化)相关推荐
- mysql嵌套子查询索引_SQL 子查询,索引优化
场景 索引优化 单列索引 多列索引 索引覆盖 排序 场景 我用的数据库是mysql5.6,下面简单的介绍下场景 课程表 create table Course( c_id int PRIMARY KE ...
- mysql多表连接 索引_MySQL多表查询之外键、表连接、子查询、索引
一.外键: 1.什么是外键 2.外键语法 3.外键的条件 4.添加外键 5.删除外键 1.什么是外键: 主键:是唯一标识一条记录,不能有重复的,不允许为空,用来保证数据完整性 外键:是另一表的主键, ...
- mysql模糊查询之索引优化
mysql模糊查询之索引优化 三表连查之模糊查询索引优化 注:具体用法10和11步骤. 1.t_project表 DROP TABLE IF EXISTS `t_project`; CREATE TA ...
- mysql易百_MySQL如何选择随机记录?
在本教程中,您将学习从MySQL的数据库表中选择随机记录的各种技术方法. 有时我们需要从表中选择随机记录,例如: 在博客中选择一些随机帖子,并在侧栏中显示. 在"每日报价"窗口小部 ...
- mysql查询与索引优化2
1.性能分析 Mysql Query Optimizer mysql内部有自己的优化器,当收到sql时,会按它自己认为最好的优化方式去优化 Mysql常见瓶颈 CPU:CPU在饱和的时候一般发生在数据 ...
- 记一次mysql优化 not in, not exits, left join 子查询
在某次业务逻辑中写到如下逻辑:查询学校级别的未拦截弹窗记录.而弹窗设备表(t_block_blacklist_device)有四种类型(1:学校级黑名单 2:设备级别黑名单 3:略 4:学校级白名单 ...
- mysql 子查询添加索引_mysql – 你能索引子查询吗?
我有一个表和一个如下所示的查询.有关工作示例,请参阅此 SQL Fiddle. SELECT o.property_B, SUM(o.score1), w.score FROM o INNER JOI ...
- mysql插入性能_mysql 数据量大时插入和查询性能
现在mysql中有数据33.8w的数据,然后做查询和更新或插入操作,速度很慢,基本100条数据就要1.68s.好慢啊,我要测试一下,到底慢在哪?能不能提高点速度? 参考一篇博文:http://blog ...
- mysql子查询走索引吗_MySQL中in子查询会导致无法使用索引问题(转)
MySQL的测试环境 测试表如下 create tabletest_table2 ( idint auto_increment primary key, pay_idint, pay_timedate ...
最新文章
- 【学习笔记】超简单的多项式求指(含泰勒展开式、牛顿迭代完成证明)
- akaze特征匹配怎么去掉不合适的点_图像匹配几种常见算法与实践
- 『中级篇』k8s的NodePort类型Service以及Label的简单实用(68)
- FlipView和自定义值转换器
- [pytorch、学习] - 4.6 GPU计算
- telegram定时消息_ActiveMQ(18):Message之延迟和定时消息投递
- 业务链路升级中如何做数据洞察?
- 新版CSDN编辑器示例(代码及显示样式)
- linux 统计文件字节和行数,Linux命令-统计文件中的字节数、字数、行数:wc
- MQL5 编程基础:数组
- 7.3万字肝爆Java8新特性,我不信你能看完!(建议收藏)
- 几种简单电路知识汇总
- 目前人工智能的主要研究方向都有哪些?
- 华侨大学计算机组成原理期末考试试题,计算机组成原理试卷A卷答案
- 爱优芒角逐“剧场风”,腾讯为何“按兵不动”
- 请连接虚拟服务器来配置,datastage8.7客户端连接虚拟服务器 无法连接显示 (用户名和/或密码不正确。如果使用了凭证映射,请检查凭证映射用户名和密码是否配置正确。 (80011))...
- JAVA如何自定义布局单选框,5分钟DIY一个自定义单选框单选按钮
- 实时内核μC/OS-II下的网络监控系统的设计
- 五大派玩家角逐移动资讯市场,微博如何成“另类”?
- 为什么要学C语言及C语言存在的意义,有人经常犹豫学不学C语言
热门文章
- typora打开pdf文件提示文件过大_Win7/Win10拷贝到U盘容量足够却提示文件过大的解决方法...
- git 使用writer_GitHub - Vpredictor/WriterFly: [QT/C++] 写作天下,为作家创造世界而生,执云作笔,诉尽平生意。...
- UE4角色Location远距离时动画抖动问题(float精度不够)解决方案
- matlab如何画一个平面,matlab 画平面
- 【转】OWIN是什么?
- python tempfile自动删除_Python tempfile模块生成临时文件和临时目录
- php elasticsearch 获取索引所有文档_Elasticsearch客户端主要方法的使用规则
- ArrayList、HashMap、HashSet是线程不安全的,高并发下如何解决?
- Python3 爬虫学习笔记 C17【爬虫框架 pyspider — 基本使用】
- 【Linux学习】强大的文本分析工具AWK