iis服务器助手广告
返回顶部
首页 > 资讯 > 数据库 >如何优化MySQL反连接
  • 634
分享到

如何优化MySQL反连接

2024-04-02 19:04:59 634人浏览 薄情痞子
摘要

这篇文章给大家分享的是有关如何优化Mysql反连接的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。总体来看这个环境还是相对比较繁忙的,线程大概是200多个。# mysqladmin

这篇文章给大家分享的是有关如何优化Mysql反连接的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。


总体来看这个环境还是相对比较繁忙的,线程大概是200多个。
# mysqladmin pro|less|wc -l
235
带着好奇查看慢日志,马上定位到这个语句,已做了脱敏处理。
# Time: 161013  9:51:45
# User@Host: root[root] @ localhost []
# Thread_id: 24630498  Schema: test Last_errno: 1160  Killed: 0
# Query_time: 61213.561106  Lock_time: 0.000082  Rows_sent: 7551  Rows_examined: 201945890920  Rows_affected: 0  Rows_read: 7551
# Bytes_sent: 0  Tmp_tables: 1  Tmp_disk_tables: 0  Tmp_table_sizes: 0
# InnoDB_trx_id: 2F8E5A82
SET timestamp=1476323505;
select account from t_fund_info
where money >=300 and account not in
(select distinct(login_account) from t_user_login_record where login_time >='2016-06-01')
into outfile '/tmp/data.txt';
从慢日志来看,执行时间达61213s,这个是相当惊人了,也就意味着这个语句跑了一整天。
这引起了我的好奇和兴趣,这个问题有得搞头了。
表t_fund_info数据量近200万,存在一个主键在id列,唯一性索引在account上。
CREATE TABLE `t_fund_info`
。。。
PRIMARY KEY (`id`),
  UNIQUE KEY `account` (`account`)
) ENGINE=InnoDB AUTO_INCREMENT=1998416 DEFAULT CHARSET=utf8
表t_user_login_record数据量2千多万,存在主键列id
CREATE TABLE `t_user_login_record`
。。。
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=22676193 DEFAULT CHARSET=utf8
从语句可以看出,是在做一个批量的大查询,是希望把查询结果生成一个文本文件来,但是过滤条件很有限。目前根据查询来看肯定是全表扫描。
先简单看了下过滤条件,从t_fund_info这个表中,根据一个过滤条件能过滤掉绝大多数的数据,得到1万多数据,还是比较理想的。
> select count(*)from t_fund_info where money >=300;
+----------+
| count(*) |
+----------+
|    13528 |
+----------+
1 row in set (0.99 sec)
那问题的瓶颈看来是在后面的子查询了。
把下面的语句放入一个sql脚本query.sql
select distinct(login_account) from t_user_login_record where login_time >='2016-06-01';
导出数据,大概耗时1分钟。
time mysql test < query.sql > query_rt.log
real    0m59.149s
user    0m0.394s
sys     0m0.046s
过滤后的数据有50多万,相对还是比较理想的过滤情况。
# less query_rt.log|wc -l
548652
我们来解析一下这个语句,看看里面的Not in的条件是怎么解析的。
explain extended select account from t_fund_info
where money >=300 and account not in
 (select distinct(login_account) from t_user_login_record where login_time >='2016-06-01');
show warnings;
结果如下:
Message: select `test`.`t_fund_info`.`account` AS `account` from `test`.`t_fund_info` where ((`test`.`t_fund_info`.`money` >= 300) and (not((`test`.`t_fund_info`.`account`,(select distinct 1 from `test`.`t_user_login_record` where ((`test`.`t_user_login_record`.`login_time` >= '2016-06-01') and (((`test`.`t_fund_info`.`account`) = `test`.`t_user_login_record`.`login_account`) or isnull(`test`.`t_user_login_record`.`login_account`))) having (`test`.`t_user_login_record`.`login_account`))))))
可以看到整个解析的过程非常复杂,原本简单的一个语句,经过解析,竟然变得如此复杂。

因为MySQL里面的优化改进空间相比oracle还是少很多,我决定循序渐进来尝试优化。因为这个环境还是很重要的,所以我在从库端使用mysqldump导出数据,导入到另外一个测试环境,放开手脚来测试了。
首先对于not in的部分,是否是因为生成临时表的消耗代价太高导致,所以我决定建立一个临时表来缓存子查询的数据。
> create table test_tab as select distinct(login_account) login_account from t_user_login_record where login_time >='2016-06-01';
Query OK, 548650 rows affected (1 min 3.78 sec)
Records: 548650  Duplicates: 0  Warnings: 0
这样查看这个临时表就很轻松了,不到1秒就出结果。
> select count(*)from test_tab;
+----------+
| count(*) |
+----------+
|   548650 |
+----------+
1 row in set (0.38 sec)
然后再次查看使用临时表后的查询是否解析会有改善。
explain extended select account from t_fund_info
where money >=300 and account not in(select login_account from test_tab);
show warnings;
发现还是一样,可见临时表的改进效果不大。
| Note  | 1003 | select `test`.`t_fund_info`.`account` AS `account` from `test`.`t_fund_info` where ((`test`.`t_fund_info`.`money` >= 300) and (not((`test`.`t_fund_info`.`account`,(select 1 from `test`.`test_tab` where (((`test`.`t_fund_info`.`account`) = `test`.`test_tab`.`login_account`) or isnull(`test`.`test_tab`.`login_account`)) having (`test`.`test_tab`.`login_account`)))))) |
是否是因为子查询中的数据量太大导致整个反连接的查询过程中回表太慢,那我缩小一下子查询的数据条数。
select account from t_fund_info
where money >=300 and  not exists (select login_account from test_tab where login_account=t_fund_info.account limit 1,10);
这种方式依旧很卡,持续了近半个小时还是没有反应,所以果断放弃。
是不是t_fund_info的过滤查询导致了性能问题,我们也创建一个临时表
> create table test_tab1 as select account from t_fund_info
    -> where money >=300;
Query OK, 13528 rows affected (1.38 sec)
Records: 13528  Duplicates: 0  Warnings: 0
再次查询效果依旧很不理想。
select account from test_tab1
where  not exists (select login_account from test_tab where login_account=test_tab1.account limit 1,10);
持续了20多分钟还是没有反应,所以还是果断放弃。
这个时候能想到就是索引了,我们在临时表test_tab上创建索引。
> create index ind_tmp_login_account on test_tab(login_account);
Query OK, 0 rows affected (4.31 sec)
Records: 0  Duplicates: 0  Warnings: 0
在临时表test_tab1上也创建索引。
> create index ind_tmp_account on test_tab1(account);
Query OK, 0 rows affected (0.18 sec)
Records: 0  Duplicates: 0  Warnings: 0
再次查看性能就变得很好了,运行时间0.15秒,简直不敢相信。
explain select account from test_tab1
where  not exists (select login_account from test_tab where login_account=test_tab1.account );
11364 rows in set (0.15 sec)

执行计划如下:
如何优化MySQL反连接
可见通过这种拆分,不断的猜测和排除,已经找到了一些思路。
我们开始抓住问题的本质。
首先删除test_tab1上的索引,看看执行效果如何。
> alter table test_tab1 drop index ind_tmp_account;
Query OK, 0 rows affected (0.00 sec)
Records: 0  Duplicates: 0  Warnings: 0
语句如下,执行时间0.15秒
select account from test_tab1
     where  not exists (select login_account from test_tab where login_account=test_tab1.account );    
+--------------------------------+
11364 rows in set (0.15 sec)
是否not in的方式会有很大的差别呢,持续0.18秒,有差别,但差别不大。
select account from test_tab1
     where account not in (select login_account from test_tab  );
+--------------------------------+
11364 rows in set (0.18 sec)
我们逐步恢复原来的查询,去除临时表test_tab1,整个查询持续了1.12秒。
select account from t_fund_info
where money >=300 and account not in(select login_account from test_tab);
+--------------------------------+
11364 rows in set (1.12 sec)
使用explain extended解析的内容如下:
Message: select `test`.`t_fund_info`.`account` AS `account` from `test`.`t_fund_info` where ((`test`.`t_fund_info`.`money` >= 300) and (not((`test`.`t_fund_info`.`account`,(((`test`.`t_fund_info`.`account`) in test_tab on ind_tmp_login_account checking NULL having (`test`.`test_tab`.`login_account`)))))))
这个时候,问题已经基本定位了。在反连接的查询中,在这个问题场景中,需要对子查询的表添加一个索引基于login_account,可以和外层的查询字段映射,提高查询效率。
当然在一个数据量庞大,业务相对繁忙的系统中,添加一个临时需求的索引可能不是一个很好的方案。不过我们还是在测试环境体验一下。
> create index ind_tmp_account1 on t_user_login_record(login_account);
Query OK, 0 rows affected (4 min 45.48 sec)
Records: 0  Duplicates: 0  Warnings: 0
添加索引的过程持续了近4分钟,在这个时候我们使用最开始的查询语句,性能如何呢。
select account from t_fund_info where money >=300 and account not in  (select distinct(login_account) from t_user_login_record where);
+--------------------------------+
11364 rows in set (2.52 sec)
只要2.52秒就可以完成之前20多个小时查询结果,性能简直就是天壤之别。
不过话说回来,跑批查询可以在从库上执行,从库上创建一个这样的索引,用完再删掉也是不错的选择,要么就是创建一个临时表,在临时表上创建索引,临时表的意义就在于此,不是为了做查询结果缓存而是创建索引来提高数据过滤效率。
在此有个问题就是临时表只有一个字段,创建索引的意义在哪里呢。
我画一个图来解释一下。
如何优化MySQL反连接
首先这个查询的数据是以t_fund_info的过滤条件为准,从200万数据中过滤得到1万条数据,然后两个字段通过account=login_account的条件关联,而不是先关联子查询的过滤条件 login_time,过滤完之后account的值之后再过滤login_time,最后根据not in的逻辑来取舍数据,整个数据集就会大大减少。如此一来,子查询的表千万行,性能的差别就不会是指数级的。

感谢各位的阅读!关于“如何优化MySQL反连接”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!

您可能感兴趣的文档:

--结束END--

本文标题: 如何优化MySQL反连接

本文链接: https://www.lsjlt.com/news/62531.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 如何优化MySQL反连接
    这篇文章给大家分享的是有关如何优化MySQL反连接的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。总体来看这个环境还是相对比较繁忙的,线程大概是200多个。# mysqladmin...
    99+
    2024-04-02
  • 如何优化MySQL连接数管理
    如何优化MySQL连接数管理 MySQL 是一种流行的关系型数据库管理系统,广泛应用于各种网站和应用程序中。在实际的应用过程中,MySQL 连接数管理是一个非常重要的问题,尤其是在高并...
    99+
    2024-04-02
  • 如何理解MySQL性能优化:长连接、短连接、连接池
    本篇内容介绍了“如何理解MySQL性能优化:长连接、短连接、连接池”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有...
    99+
    2024-04-02
  • 如何使用DataAdapter优化ADO.NET连接池
    这篇文章主要为大家展示了“如何使用DataAdapter优化ADO.NET连接池”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“如何使用DataAdapter优化ADO.NET连接池”这篇文章吧。...
    99+
    2023-06-17
  • 如何实现MySQL底层优化:连接池的优化与配置参数调整
    如何实现MySQL底层优化:连接池的优化与配置参数调整引言MySQL是一种常用的开源数据库管理系统,它的性能直接影响到系统的稳定性和响应速度。而连接池是一种重要的优化手段,可以有效地减少系统连接数据库的开销。本文将介绍如何对MySQL连接池...
    99+
    2023-11-08
    MySQL 连接池 参数调整
  • MySQL连接数怎么优化和配置
    本文小编为大家详细介绍“MySQL连接数怎么优化和配置”,内容详细,步骤清晰,细节处理妥当,希望这篇“MySQL连接数怎么优化和配置”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。...
    99+
    2023-04-22
    mysql
  • SpringBoot优化连接数
    由于springboot内置web容器是Tomcat,所以我们在使用springboot时,如果内置Tomcat参数不满足要求时,可按需优化。 SpringBoot内置Tomcat,在默认设置中,Tomcat的最大线程数是200,最大连接数...
    99+
    2023-08-17
    java tomcat spring boot mysql
  • 如何实现优化centos远程SSH连接
    本篇内容介绍了“如何实现优化centos远程SSH连接”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!①通过ls -l /etc/init.d...
    99+
    2023-06-10
  • mysql如何优化
    本篇文章给大家分享的是有关mysql如何优化,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。mysql如何优化1.使用小的整数类型2.无特殊情况...
    99+
    2024-04-02
  • 如何优化MySQL外键和主键之间的自动连接效率?
    如何优化MySQL外键和主键之间的自动连接效率? 在数据库设计中,外键和主键之间的关系是非常重要的。当查询涉及多个表时,经常需要使用外键和主键进行连接操作。然而,如果不注意优化这些连接...
    99+
    2024-04-02
  • MySQL SSL 连接性能分析与优化建议
    MySQL SSL 连接性能分析与优化建议随着网络安全问题的日益凸显,越来越多的应用程序选择使用 SSL 加密技术来保护数据传输的安全性。在 MySQL 数据库中, SSL 连接也被广泛应用。然而,由于 SSL 连接需要进行加密与解密操作,...
    99+
    2023-10-22
  • eclipse如何连接mysql
    eclipse连接mysql的方法:需要准备个mysql的jar驱动文件,下载地址https://www.mysql.com/products/connector/找到JDBC Driver for MySQL (Connector/J),...
    99+
    2024-04-02
  • mysql如何连接mysqld
    这篇文章给大家分享的是有关mysql如何连接mysqld的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。1、通过本地socket文件连接,只能在本地使用,不依赖IP和端口。-- socket文件路径通过下...
    99+
    2023-06-20
  • django如何连接mysql
    要连接MySQL数据库,首先需要安装MySQL驱动程序。在Django中,可以使用`mysqlclient`或`PyMySQL`两个...
    99+
    2023-10-09
    django mysql
  • navicat如何连接mysql
    这篇文章主要介绍navicat如何连接mysql,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!连接方法:1、点击工具栏中的“连接”,选择“MySQL”,进入连接设置界面;2、填写“连...
    99+
    2024-04-02
  • MySQL中的反连接有什么用
    这篇文章给大家分享的是有关MySQL中的反连接有什么用的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。    在表的连接上,半连接,反连接本身很平常,但是统计...
    99+
    2024-04-02
  • 【MySQL】sql如何优化?
    一、优化步骤 (1)通过SQL监控、请求、日志等找出耗时的SQL语句; (2)使用Explain方式查看SQL耗时的具体原因; (3)根据实际情况解决:索引、缓存、左右连接 二、Explain select_type:简单查询or复杂查询?...
    99+
    2023-09-16
    sql mysql 数据库
  • mysql如何优化join
    本篇文章为大家展示了mysql如何优化join,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。 mysql 在join 表的时候相当类型的...
    99+
    2024-04-02
  • k8s长连接怎么优化
    要优化K8s长连接,可以考虑以下几点: 调整TCP连接参数:调整TCP连接的超时时间、重传次数等参数,以适应长连接的特性。可以通...
    99+
    2023-10-27
    k8s
  • 如何理解SQL优化中连接谓词推入
    这篇文章将为大家详细讲解有关如何理解SQL优化中连接谓词推入,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。 SQL优化之连接谓词...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作