前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >MySQL表连接优化的初步分析

MySQL表连接优化的初步分析

作者头像
jeanron100
发布于 2018-08-22 06:35:19
发布于 2018-08-22 06:35:19
1.6K00
代码可运行
举报
运行总次数:0
代码可运行

每每一些很深刻的优化案例时,就会无比想念Oracle里的优化技巧,因为无论是从工具还是信息,都会丰富许多。

数据库技术就是这么一路走过来,MySQL的优化器也是,所以在MySQL最流行的情况下,我只能更多的去摸清楚优化器里的一些实现差异。

还是昨天的那个SQL优化案例,我会从另外几个维度来说下优化的思路。

伪SQL如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    update big_table,
    (xxxxxx ) small_table
    set xxxxx
    where xxxxxx;
看起来这个语句很简单,如果展开,完整的SQL如下:
UPDATE 
 digital_test.comprehensive_orders co , --千万级大表
 ( SELECT 
    uoi.order_code ,
    MAX(uoi.item_stat) AS costat ,
    SUM(uoi.winning_gold) AS winningGold ,
    SUM(uoi.winning_gold-uoi.item_price) as profit 
   FROM  
   test.user_order_items uoi ,  --近千万级大表
   ( SELECT DISTINCT a.order_code FROM test.user_order_items a WHERE a.match_id=35303 AND a.item_pid=51 AND a.item_stat>0 )

    AS temp0 
   WHERE uoi.order_code=temp0.order_code GROUP BY uoi.order_code HAVING bit_and(uoi.item_stat>>1)!=0  

 ) 
   AS temp1 
   SET 
    co.co_stat=(CASE WHEN temp1.coStat IN (6,9) THEN 4 ELSE temp1.coStat END),
    co.co_winning_gold=temp1.winningGold, co.co_test_draw_time='2018-08-07 16:20:45', 
    co.co_share_income_outcome = CASE WHEN co.co_order_type=4 THEN ( CASE WHEN temp1.profit>0 THEN ROUND(ifnull(co.co_share_payoff_ratio,0) * temp1.profit) ELSE 0 END ) ELSE 0 END ,
    co.co_award_id=35309 
WHERE co.co_order_code=temp1.order_code AND co.co_stat=1

我从几个维度来简单说一下,核心的优化思想还是“平衡”

  1. 首先我们定位到最初的解决方案。

伪SQL可以更加丰富一些。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
UPDATE 
 digital_test.comprehensive_orders co ,  
 ( SELECT 
    xxxx
   FROM  
   test.user_order_items uoi ,
   ( SELECT DISTINCT a.order_code FROM test.user_order_items a WHERE a.match_id=35303 AND a.item_pid=51 AND a.item_stat>0 )

    AS temp0 
   WHERE uoi.order_code=temp0.order_code GROUP BY uoi.order_code HAVING bit_and(uoi.item_stat>>1)!=0  

 ) 
   AS temp1 
   SET 
   xxxx
WHERE co.co_order_code=temp1.order_code AND co.co_stat=1

其中temp1里的查询过滤的结果集是个位数,而外层的表digital_test.comprehensive_orders数据上千万,但是关联的条件是走主键的。

我们画个图来说。

上面这种情况其实MySQL是很容易区分的,难就难在这个情况真实情况是这样的。

如果碰到这种情况,MySQL优化器就有点懵了。这两个大表自己关联,结果集到底有多大,因为没有更丰富的信息,要定位还是有些难的。

所以从执行计划来看,为什么性能差,最后优化器的判断是对两个大表做了全表扫描。

所以我的思路是通过对where条件的过滤来做的,既然他没法确定更小的结果集,那么我就在where部分过滤,SQL肯定会优先处理where的部分。得到的是小的结果集,自然压力就小了。

还有没有更好的方案呢,同事也提供了一些思路,最后的方案是根据他的建议来做的。

这个改进是怎么做的呢, 带颜色的部分就是改动的地方。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
UPDATE digital_test.comprehensive_orders co,
    (
    SELECT xxxxx
    FROM 
    (
    SELECT  a.order_code
    FROM test.user_order_items a
    WHERE a.match_id=35303
    AND a.item_pid=51
    AND a.item_stat>0
    ) AS temp0  join test.user_order_items uoi 
    on uoi.order_code=temp0.order_code
    GROUP BY uoi.order_code HAVING bit_and(uoi.item_stat>>1)!=0
     ) AS temp1
SET
 xxxxx
WHERE co.co_order_code=temp1.order_code
            AND co.co_stat=1 ;

可以看到这种改法,没有添加额外的SQL逻辑,把原来的表关联改为了join的方式,效果是立竿见影。

这里的改动思路是把原来的大表小表关联,改为小表大表关联,然后改为join的写法。

那么这里就有两个问题,

  1. 同样是表关联,小表大表关联和大表小表关联,这种写法在MySQL那么重要吗?
  2. 是否join的写法效果要更好一些?

要验证这两个问题,其实也不难。我们使用如下的SQL来验证。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
UPDATE 
 digital_test.comprehensive_orders co ,
 ( SELECT 
   xxxxx
   FROM 
   ( SELECT DISTINCT a.order_code FROM test.user_order_items a WHERE a.match_id=35303 AND a.item_pid=51 AND a.item_stat>0 )
    AS temp0 ,
 test.user_order_items uoi 
   WHERE uoi.order_code=temp0.order_code GROUP BY uoi.order_code HAVING bit_and(uoi.item_stat>>1)!=0  
 ) 
   AS temp1 
   SET 
   xxxx
WHERE co.co_order_code=temp1.order_code AND co.co_stat=1

这种改法简直天然无公害,执行效率也是杠杠的。在这个场景下,确实顺序还是有很大的关联的。

然后第二个问题,是否join的方式要更好一些?

我们可以把表关联写为大表 join 小表,看看效果如何。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
UPDATE 
 digital_test.comprehensive_orders co ,
 (SELECTxxxx
    FROM 
       test.user_order_items uoi join(
    SELECT  a.order_code
    FROM test.user_order_items a
    WHERE a.match_id=35303
    AND a.item_pid=51
    AND a.item_stat>0
    ) AS temp0
  on uoi.order_code=temp0.order_code
    GROUP BY uoi.order_code HAVING bit_and(uoi.item_stat>>1)!=0 
 ) 
   AS temp1 
   SET 
  xxxxx
WHERE co.co_order_code=temp1.order_code AND co.co_stat=1

这种情况下,SQL的性能是比较差的,大概1分钟后才有反应。

所以在这种场景下,join的写法明显没有特殊的改进。

我们简单总结一下,在这个SQL优化场景中,为了得到更好的性能,需要做到一个平衡,即小表和大表的关联方式,效率是最佳的,至于你是写成join还是逗号分隔的表关联,从目前的测试来看,差别不大。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-08-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 杨建荣的学习笔记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
python随机生成字符串学习
random.choice从序列中获取一个随机元素。其函数原型为:random.choice(sequence)。参数sequence表示一个有序类型。这里要说明 一下:sequence在python不是一种特定的类型,而是泛指一系列的类型。list, tuple, 字符串都属于sequence。有关sequence可以查看python手册数据模型这一章。下面是使用choice的一些例子:
py3study
2020/01/09
1.4K0
在Python中使用大写字母和数字生成随机字符串
The objective of this article is to Generation of the random alphanumeric string with uppercase and numbers. To generate the random string, we could use the following modules from python,
用户7886150
2021/01/09
1.7K0
python生成随机密码串
   今天修改服务器密码,想来想去不知道设置什么密码比较好,索性设置随机数吧。python当中的random模块可以生成随机数,主要用这个生成随机密码。
py3study
2020/01/08
5.1K0
[oeasy]python080如何生成验证码_随机数字密码_真随机
import random # 生成一个6位的随机数字,每位数字可以是0-9 random_number = "" for _ in range(6): random_digit = random.randint(0, 9) random_number += str(random_digit) # 显示生成的随机数字 print(f"生成的6位随机数字是: {random_number}") 结果
oeasy
2025/03/29
450
[oeasy]python080如何生成验证码_随机数字密码_真随机
python生成随机数、随机字符、随机字符串
本文是基于Windows 10系统环境,实现python生成随机数、随机字符、随机字符串:
用户7886150
2020/12/22
2.7K0
Python 随机字符串
当调用方法 choice(string.ascii_uppercase) 的意思是将会随机从大写字符中挑选出一个字符。
HoneyMoose
2021/03/19
6560
Python 随机字符串
python常用运维脚本实例
file是一个类,使用file('file_name', 'r+')这种方式打开文件,返回一个file对象,以写模式打开文件不存在则会被创建。但是更推荐使用内置函数open()来打开一个文件 .
菲宇
2019/06/12
1.9K0
rc4+ctf常用编码加密shellcode
本文不会解释rc4加密是什么,以及ctf编码在我的理解中为一个大类,并非单独一种编码形式,当然不管是rc4还是ctf编码,其宗旨都是为了使字符串变得“毫无意义”从而达成无法被杀软正确的检查出是shellcode。 其实这篇文章更多的算是踩坑记录,因为本身代码的实现复制粘贴即可,讲加密代码的原理也大可不必,不可逆就行了。 目前针对rc4网上有不同的写法,主要根本是环境的不同,分别有
Elapse
2022/10/27
1.3K0
rc4+ctf常用编码加密shellcode
常用的生成测试数据的python脚本,用了都说好
生成接口自动化测试数据时,Python提供了丰富的库和工具来帮助我们创建各种类型的数据, 以下是常用的Python脚本示例,用于生成不同类型的测试数据。
可可的测试小栈
2024/11/23
2570
常用的生成测试数据的python脚本,用了都说好
Python如何随机生成一个字符串?
随机数、随机字符串的生成,是日常开发中,非常常见的。例如,我们常见的登录页面的图片验证码的随机字符串,就可以使用到今天学到的知识。快来掌握这一技巧,提高开发效率吧。
TalkPython
2020/12/11
9360
Python授权码生成器(密码生成器)
有时候我们需要为自己的产品设置一些使用权限 ,这就需要随机授权码生成器。当然这是简单的随机生成器,像Adobe这种授权码是需要一定的加密算法生成,然后再验证授权码是否正确,而不是简单的生成。
里克贝斯
2021/05/21
3.1K0
Python授权码生成器(密码生成器)
Python基础模块学习03-随机函数
random 模块实现了各种分布的伪随机数生成器。可以用于模拟或者任何产生随机输出的程序。对于整数,从范围中有统一的选择。对于序列,存在随机元素的统一选择、用于生成列表的随机排列的函数、以及用于随机抽样而无需替换的函数。
Linux运维技术之路
2022/06/07
3360
Python基础模块学习03-随机函数
[781]python去除字符串中开头|结尾|所有字母、数字
参考:https://blog.csdn.net/qq_25792799/article/details/80322889 https://blog.csdn.net/qq_40771567/article/details/86561158 https://www.cnblogs.com/pyse/p/9847812.html http://dy.163.com/v2/article/detail/DMA5CHFN0511RVML.html
周小董
2020/04/08
2.9K0
Python简易验证码生成程序
from PIL import Image, ImageDraw, ImageFont import random import string #所有可能的字符,主要是英文字母和数字 characters = string.ascii_letters+string.digits #获取指定长度的字符串 def selectedCharacters(length): '''length:the number of characters to show''' result = "" fo
Python小屋屋主
2018/04/16
7120
python-PIL模块画图
python中执行mysql遇到like 怎么办 ? ​ ​sql = "SELECT * FROM T_ARTICLE WHERE title LIKE '%%%%%s%%%%'" % searchStr
py3study
2020/01/09
1.1K0
Python生成大量随机人员信息
有时候我们会需要大量数据来演示或者测试某些功能,但是可能无法获得这些数据,或者担心泄露信息而不想使用真实数据。这时,我们可以自己生成一些随机数据。 import random import string def getEmail(): # of course you can extend the following list suffix = ['.com', '.org', '.net', '.cn'] characters = string.ascii_letters + strin
Python小屋屋主
2018/04/16
9750
如何用Python生成符合FIPS审计规则的密码
在当今的网络安全环境下,强密码的重要性不言而喻。而在企业级应用和政府项目中,通常还需要满足特定的安全标准和审计要求。美国联邦信息处理标准(FIPS,Federal Information Processing Standards)就是其中一个重要的标准。在本篇文章中,我们将通过Python实现一个生成符合FIPS审计规则的密码的方法。
运维开发王义杰
2023/09/19
2410
如何用Python生成符合FIPS审计规则的密码
使用python3来生成安全的随机密码
最近1年自学了python,发现python的应用场景挺多,自己百度了加自己稍微修改,写了段可以随时生成指定长度的安全随机密码 #C:\Python36 #coding=utf-8 import string from random import choice passwd_length = int(input('The length of password: '))        #密码的长度 passwd_count = int(input('The number of password list
py3study
2020/01/06
1.1K0
Python 实战:自动生成密码并保存
在今天的数字化世界中,密码是我们保护个人信息和保障数据安全的重要工具。然而,许多人在创建密码时往往会遇到一些困难,例如想不到足够安全的密码,或者难以记住复杂的密码。在本文中,我们将介绍一个简单的 Python 程序,它可以帮助我们生成随机且安全的密码,并将其保存到文件中。
剑指工控
2024/05/11
2770
Python 实战:自动生成密码并保存
软件测试|Python random模块,超乎想象的强大
Python的random模块是一个非常强大的工具,用于生成随机数和随机选择。它提供了许多函数和方法,可以满足各种随机化需求。本文将介绍random模块的基本功能和常见用法,以帮助读者更好地理解和利用这个模块。
霍格沃兹测试开发Muller老师
2023/09/07
2150
相关推荐
python随机生成字符串学习
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验