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 未优化的语句:

18949d524fa4fde5d9c9b69e47a4cc36.png

(相关子查询是使用外部查询中的值的子查询)

EXPLAIN 优化的语句:

59bbae8e2618452d5334c8d0aea435cd.png

我的理解:优化前,子查询是相关子查询,对于外部产生的每个值,都要执行一次子查询;优化后,子查询不再是相关子查询,只需要执行一次子查询并缓存中间结果,外部查到的每个值去缓存的中间结果里比对一下就行了。

(有人说是能不能用索引的原因——这么说应该是不对的)

完整查询的后端响应速度对比:

前:

e186e3540f0588a7ff727aaf3ca3706f.png

后:

90c9628611f695d2f60d86ed287a9734.png

索引优化

对于这么小的数据规模,时间还是太长了… 看前面explain执行计划的截图,嗯,没有索引…

给t1的vc_bankacco加上索引之后

2bd9825ec8b40f22d316e27091cbfbc8.png

c9276e644edb9b8c03c5a68c1da56b22.png

解释执行计划:

d27f095872ae385f4a486f52c6012cf1.png

查询和网页响应用时大幅缩短:

4c78a47e3f89acf7118e92abbdb125d8.png

再看sql里还有三个join:

71b3d55ee0cb17a1dc55b2922a42247c.png

用的都是ot_dic_tdictionaryentry这张表的t4.vc_entry_value字段,那么试着给这个字段也加上索引吧,然后用时如下:

53c1493047e8ddd195a77aa2cc31805a.png

是的,时间反而变长了!

explain执行计划:

c902c26d662ce6b4dd438563a6fd9526.png

所以变慢原因是:

没加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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/442614.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

创建mysql的表怎么显示00_Mysql sql_mode设置 timestamp default 0000-00-00 00:00:00 创建表失败处理...

往数据库里创建新表的时候报错:[Err] 1067 - Invalid default value for updateTimeDROP TABLE IF EXISTS passwd_reset;CREATE TABLE passwd_reset (id int(11) NOT NULL AUTO_INCREMENT,staffId int(11) DEFAULT NULL,toEmail varchar(50) DEFAULT NULL,token var…

mysql sqlite转换_数据库转换工具(SqliteToMysql)

SqliteToMysql是一款用于SQLITE和MYSQL之间的数据库转换工具。它能够将SQLITE数据转换成MYSQL数据库,让用户自主配置转换条件,满足用户的数据库格式需要。。相关软件软件大小版本说明下载地址SqliteToMysql是一款用于SQLITE和MYSQL之间的数据库转换工具。…

mysql 查看集群状态_MySQL数据库集群正确配置步骤

类型:电子教程大小:8.5M语言:中文 评分:8.3标签:立即下载对MySQL数据库集群进行正确配置的实际操作步骤,以及对其概念的讲述,如果你对其相关的实际操作有兴趣了解的话,以下的文章将会…

oschina mysql limit_MySQL 用 limit 为什么会影响性能?

点击上方“武培轩”,选择“设为星标”技术文章第一时间送达!一,前言首先说明一下MySQL的版本:mysql> select version();-----------| version() |-----------| 5.7.17 |-----------1 row in set (0.00 sec)表结构:m…

mysql外键教程_关于MySQL外键的简单学习教程

在MySQL中,InnoDB引擎类型的表支持了外键约束。外键的使用条件:1.两个表必须是InnoDB表,MyISAM表暂时不支持外键(据说以后的版本有可能支持,但至少目前不支持);2.外键列必须建立了索引,MySQL 4.1.2以后的版…

mybatis mysql 分页sql语句_MySql实现分页查询的SQL,mysql实现分页查询的sql语句(转)...

http://blog.csdn.net/sxdtzhaoxinguo/article/details/51481430摘要:MySQL数据库实现分页查询的SQL语句写法!一:分页需求:客户端通过传递start(页码),limit(每页显示的条数)两个参数去分页查询数据库表中的数据&#…

mysql索引详细介绍简书_Mysql索引介绍

数据库索引,是数据库管理系统中一个排序的数据结构,以协助快速查询、更新数据库表中数据。索引的实现通常使用B树及其变种B树。在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据&a…

在mysql中建立聚簇索引_给我一分钟,让你彻底明白MySQL聚簇索引和非聚簇索引...

推荐阅读:吊打面试官!MySQL灵魂100问,你能答出多少?MySQL的InnoDB索引数据结构是B树,主键索引叶子节点的值存储的就是MySQL的数据行,普通索引的叶子节点的值存储的是主键值,这是了解聚簇索引和非…

根据从日期控件选定的时间以表格形式显示数据_VB项目开发FlexGrid控件使用讲解...

FlexGrid控件使用介绍大家好,在VB开发管理系统中,FlexGrid控件使用是非常普遍的。用FlexGrid ActiveX控件可以在 Visual Basic的窗体中创建一个电子数据表格,也可称之为网格。FlexGrid ActiveX控件可以在网格中显示任何类型的表格式数据&…

arduino无源蜂鸣器歌曲编码_Arduino加无源蜂鸣器,播放音乐《葫芦娃》

Arduino加无源蜂鸣器,播放音乐《葫芦娃》#define NOTE_D0 -1#define NOTE_D1 294#define NOTE_D2 330#define NOTE_D3 350#define NOTE_D4 393#define NOTE_D5 441#define NOTE_D6 495#define NOTE_D7 556#define NOTE_DL1 147#define NOTE_DL2 165#define NOTE_DL3…

mysql爆内存_线上MySQL数据库机器内存爆掉原因分析与解决

本文主要向大家介绍了线上MySQL数据库机器内存爆掉原因分析与解决,通过具体的内容向大家展现,希望对大家学习MySQL数据库有所帮助。现象:阿里金融某业务的MySQL机器的内存每隔几天就会增长,涨上去后,却不下来。累积后内…

mysql atlas更新问题_Atlas几种常见故障解决(不定期更新)

1)使用atlas却发现“读库闲置,框架还是去主库读写数据”配置完atlas之后,发现使用jdbc框架的话,读库和写库各司其职,但是使用mybatis框架之后,就发现框架的读写都去了主库,把读库放置一边,那么这…

如何更改mysql服务名_技术小百科 |【云小课】数据复制服务如何实现对象名映射...

数据复制服务(Data Replication Service,简称DRS)是一种易用、稳定、高效、用于数据库在线迁移和数据库实时同步的云服务。数据复制服务提供了在线迁移、备份迁移、数据同步、数据订阅和多活灾备等多种功能。数据复制服务支持哪些对象名映射数据复制服务的数据同步功…

python 二维强度图_荐 python数据分析matplotlib库使用之二维图形绘制

本篇内容会在后期不定时更新什么是matplotlibmatplotlib是最流行的python底层绘图库,主要做数据可视化图表。为什么要学习matplotlib能将数据进行可视化,更直观的呈现使数据更加客观,更具有说服力二维图绘制matplotlib库的基本使用之折线图导…

mysql产品优化方案_mysql的优化方案

简介在本文中,主要写一下自己所查阅和理解的mysql优化方案.我的理解是数据库的优化对于我们非专业人员,mysql的优化也没那么复杂了,真的要玩转mysql的话,肯定得需要很多年的经验了.参考链接:优化方案1.搜索引擎的优化mysql搜索引擎用的比较多的有以下三中InnoDBMEMORYMyISAMInn…

python数据爬虫代码_python如何示例爬虫代码

python爬虫代码示例的方法:首先获取浏览器信息,并使用urlencode生成post数据;然后安装pymysql,并存储数据到MySQL即可。python爬虫代码示例的方法:1、urllib和BeautifuSoup获取浏览器信息from urllib import requestre…

kali linux查看网卡_CentOS7.6安装无线网卡驱动|Linux如何安装网卡驱动|Linux如何让配置网卡...

此前提到,Thinkpad E490安装CentOS7.6遇到内核崩溃的问题,解决之后,安装CentOS7.6操作系统成功。安装时发现,系统能够检测到有线网卡,但无法检测到无线网卡,说明CentOS7.6对此无线网卡的支持不足&#xff0…

python本地编译器_Python学习札记(0)——Python开发环境搭载及推荐几款Python编译器...

1、进入网址:http://www.python.org/download/#id102、选择版本:其中有两个Python版本,一个为3.0以上版本,一个为2.7版本,主要区别有一些特定的软件只支持2.7版本其中的两个windows版本为:Python 3.3.3 Win…

如何将mysql的数据库渲染到页面_vue.js实现数据库的JSON数据输出渲染到html页面功能示例...

本文实例讲述了vue.js实现数据库的JSON数据输出渲染到html页面功能。分享给大家供大家参考,具体如下:1、首先通过json.php把数据库给输出为json格式的数据[{"id":1,"resname":"百度","resimg":"http://www…

java模块_Java 9 揭秘(2. 模块化系统)

文 by / 林本托Tips做一个终身学习的人。在此章节中,主要介绍以下内容:在JDK 9之前Java源代码用于编写,打包和部署的方式以及该方法的潜在问题JDK 9中有哪些模块如何声明模块及其依赖关系如何封装模块什么是模块路径什么是可观察的模块如何打…