首页 > 数据库 >如何强制SQL走性能更优的hash join

如何强制SQL走性能更优的hash join

时间:2023-10-13 10:59:49浏览次数:39  
标签:code join timestamp SQL date hash day

本文分享自华为云社区《【SQL优化】为什么有时候无法走执行性能更优的hashjoin》,作者: leapdb。

1. hash join通常优于nestloop join

通常nestloop join的复杂度是O(N方),hash join时间复杂度是O(N),所以我们一般倾向于使用hash join。   在SQL脚本调优过程中通常有两种方式,强制走hash join方式:

1. 在session级关闭nestloop方式,set enable_nestloop to off;

2. 在SQL中通过 /*+ hashjoin(a b) */ 方式,让a和b表走hash join;  
CREATE DATABASE test_td WITH DBCOMPATIBILITY='td';

create table dim_day(day_code char(8));
create table dwr_rpo as select current_date - 1 as day_code; --返回了date类型

test_td=# \d+ dwr_rpo
                       Table "public.dwr_rpo"
  Column  | Type | Modifiers | Storage | Stats target | Description 
----------+------+-----------+---------+--------------+-------------
 day_code | date |           | plain   |              | 
Has OIDs: no
Distribute By: ROUND ROBIN
Location Nodes: ALL DATANODES
Options: orientation=row, compression=no

explain select *
from dwr_rpo a
left join dim_day c
on c.day_code = a.day_code;

id |                  operation                   | E-rows  | E-distinct | E-memory | E-width |   E-costs    
---+----------------------------------------------+---------+------------+----------+---------+--------------
 1 | ->  Streaming (type: GATHER)                 | 1310148 |            |          |    1694 | 279235196.70 
 2 |    ->  Nested Loop Left Join (3, 4)          | 1310148 |            | 1MB      |    1694 | 279229682.93 
 3 |       ->  Seq Scan on dwr_rpo a              | 1310148 |            | 1MB      |    1676 | 46589.16     
 4 |       ->  Materialize                        |  109575 |            | 16MB     |      22 | 3747.76      
 5 |          ->  Streaming(type: BROADCAST)      |  109575 |            | 2MB      |      22 | 3565.14      
 6 |             ->  Seq Scan on dim_day c        |   36525 |            | 1MB      |      22 | 272.75       

               Predicate Information (identified by plan id)                
-----------------------------------------------------------------------------
  2 --Nested Loop Left Join (3, 4)
        Join Filter: ((c.day_code)::timestamp without time zone = a.day_code)

mermaid-diagram-2023-09-06-114052.png

可是,以上SQL无论用哪种方式都走不上hash join。我们需要看一下,join两端的数据类型是否支持hash比较。   1. 为什么有时候无法走执行性能更优的hashjoin

不同数据类型计算hash函数不同,互不兼容的数据类型无法进行hash比较。

2. 为什么hashjoin秒级,nestloop需要两个小时

nestloop复杂度:131w * 10w = 1310亿

hashjoin复杂度:131w

所以两种方式性能差距很大。   3. 为什么有类型转换,还不能hash join

看似类型相近,但由于两端的精度,格式,有无时区等不一样,无法认为直接相等。

4. 都哪些数据类型间的join不支持hash?
select oprname,oprkind,oprcanhash,
  (select typname from pg_type where oid=oprleft) oprleft,
  (select typname from pg_type where oid=oprright) oprright 
from pg_operator 
where oprname='=' and oprcanhash='f';

 oprname | oprkind | oprcanhash |    oprleft    |   oprright    
---------+---------+------------+---------------+---------------
 =       | b       | f          | xid           | int8
 =       | b       | f          | xid32         | int4
 =       | b       | f          | tid           | tid
 =       | b       | f          | box           | box
 =       | b       | f          | path          | path
 =       | b       | f          | tinterval     | tinterval
 =       | b       | f          | money         | money
 =       | b       | f          | circle        | circle
 =       | b       | f          | lseg          | lseg
 =       | b       | f          | line          | line
 =       | b       | f          | bit           | bit
 =       | b       | f          | varbit        | varbit
 =       | b       | f          | date          | timestamp
 =       | b       | f          | date          | timestamptz
 =       | b       | f          | timestamp     | date
 =       | b       | f          | timestamptz   | date
 =       | b       | f          | timestamp     | timestamptz
 =       | b       | f          | timestamptz   | timestamp
 =       | b       | f          | tsvector      | tsvector
 =       | b       | f          | tsquery       | tsquery
 =       | b       | f          | record        | record
 =       | b       | f          | hll           | hll
 =       | b       | f          | hll_hashval   | hll_hashval
 =       | b       | f          | roaringbitmap | roaringbitmap
(24 rows)
  主要是timestamp, timestamptz, date间互相join是无法走hash。其它数据类型不常见。   开发建议:join两端的数据类型尽量一致或互相兼容。   5. 为什么 oracle 兼容模式没有问题,td兼容模式有问题?

current_date 在TD兼容模式下为date类型;

current_date 在Oracle兼容模式下为timestamp类型;

点击关注,第一时间了解华为云新鲜技术~

 

标签:code,join,timestamp,SQL,date,hash,day
From: https://www.cnblogs.com/huaweiyun/p/17761544.html

相关文章

  • MySQL的index merge(索引合并)导致数据库死锁分析与解决方案
    背景在DBS-集群列表-更多-连接查询-死锁中,看到9月22日有数据库死锁日志,后排查发现是因为mysql的优化-indexmerge(索引合并)导致数据库死锁。定义indexmerge(索引合并):该数据库查询优化的一种技术,在mysql5.1之后进行引入,它可以在多个索引上进行查询,并将结果合并返回。mysql数......
  • SQL注入一些方法
    select(ascii(substr(database(),1,1)))>91这个查询语句的目的是检查数据库名的第一个字符的ASCII码是否大于91。让我们分解这个查询以便更好地理解它的含义:database():这是一个MySQL函数,用于返回当前数据库的名称。substr(database(),1,1):这是一个MySQL函数,用于从数据库名称......
  • idea 中无法连接 sql server 数据库,报错 [08S01] 驱动程序无法通过使用安全套接字层(S
    报的错误信息如下:[08S01]驱动程序无法通过使用安全套接字层(SSL)加密与SQLServer建立安全连接。错误:“PKIXpathbuildingfailed:sun.security.provider.certpath.SunCertPathBuilderException:unabletofindvalidcertificationpathtorequestedtarget”。ClientC......
  • MySQL的驱动表与被驱动表
    驱动表与被驱动表的含义在MySQL中进行多表联合查询时,MySQL会通过驱动表的结果集作为基础数据,在被驱动表中匹配对应的数据,匹配成功合并后的临时表再作为驱动表或被驱动表继续与第三张表进行匹配合并,直到所有表都已匹配完毕,最后将结果返回出来。匹配算法:Nested-LoopJoin(嵌套循环连......
  • MHA设置mysql的主从及遇到的坑
    记录一下搭建MHA主从的完整过程,同时也把自己部署过程中遇到的坑写进来参考链接:https://blog.csdn.net/m0_49526543/article/details/109483659https://blog.csdn.net/hahaxixi131/article/details/122282665https://www.cnblogs.com/jiabrother/p/14108302.html 先说一下......
  • Skywalking APM监控系列(二、Mysql、Linux服务器与前端JS接入Skywalking监听)
    前言上篇我们介绍了Skywalking的基本概念与如何接入.NetCore项目,感兴趣可以去看看:SkywalkingAPM监控系列(一丶.NET5.0+接入Skywalking监听)本篇我们主要讲解一下Skywalking如何接入mysql数据库监听与Linux服务器的监听其实从Skywalking设计之初应该只是单独的链路跟踪,发......
  • MYSQL GROUP BY 对多个字段进行分组
    在平时的开发任务中我们经常会用到MYSQL的GROUPBY分组,用来获取数据表中以分组字段为依据的统计数据。比如有一个学生选课表,表结构如下:Table:Subject_SelectionSubjectSemesterAttendeeITB0011JohnITB0011BobITB0011Micke......
  • SQL注入篇
    SQL注入篇Sql注入的一些零碎知识点Access数据库默认路径存放在网站的:/db/db.mdb.Mdb后缀就是access数据库文件的后缀名123asp.jpg的后门连接不成功123asp;.jpg的后门可以连接成功(虽然还是图片格式,但却可以连接成功)这是利用了解析漏洞这是iis6版本的解析漏洞在ii......
  • 深入MySQL索引,这篇千万不能错过
    大家好,我是【码老思】,索引是一个数据库绕不开的话题,今天和大家一起聊聊。1.索引索引是对数据库表中一列或多列的值进行排序的一种结构。MySQL索引的建立对于MySQL的高效运行是很重要的,索引可以大大提高MySQL的检索速度。索引只是提高效率的一个因素,如果你的MySQL有大数据量......
  • hive数据清洗,导入mysql
    --用于清洗的表createtabledata1(`ip`stringcomment'城市',`date1`stringcomment'日期',`day`stringcomment'天数',`traffic`doublecomment'流量',`type`stringcomment'类型:视频video或文章art......