达梦反连接与半连接

半连接与反连接

除了内连接,外连接等还有两种特殊的连接查询:半连接(Semi Join)和反连接(Anti Join)。由于 SQL 标准没有定义这两种连接查询语法,而是通过子查询的方式实现相同的效果。

1.半连接

半连接返回左表中与右表至少匹配一次的数据行,通常体现为 EXISTS 或者 IN 子查询。半连接的示意图如下:

 

table1 中的 id = 2 在 table2 中没有对应的数据,所以连接的结果不包含该记录。

半连接只会返回左表中的数据,右表只用于条件判断。另外,即使右表中存在多个匹配的数据,左边中的数据只返回一次。半连接通常用于存在性判断,例如哪些顾客购买了产品,而不需要知道他们购买的具体产品和数量。

测试数据

DROP TABLE T1 CASCADE;

DROP TABLE T2 CASCADE;

CREATE TABLE T1 (ID INTEGER,NAME VARCHAR(128));

CREATE TABLE T2 (ID INTEGER,NAME VARCHAR(128));

begin

for i in 1..100000 loop

insert into T1 values(i,'dameng'||i);

insert into T2 values(i+500,'damengsh'||i);

end loop;

end;

T1,T2表中各10万条数据。

查询T1表ID在T2表中存在的行数。因为T1的ID是1到100000,T2的ID是501到100500。很显然,sql执行结果是100000-500=99500。执行计划如下:

SQL> EXPLAIN SELECT COUNT(*) FROM T1 A  WHERE A.ID IN (SELECT B.ID FROM T2 B);

 

通过执行计划我们可以看到先计算T2表的非关联子查询(全表扫描,去重),然后与T1表做HASH2 INNER JOIN。

很显然这个sql我们可以改成exists的关联子查询,如下:

SELECT  count(*) FROM T1 A

WHERE  EXISTS(SELECT 1 FROM T2 B where A.ID=B.ID);

查看这个sql的执行计划

 

可以看到,与上一个SQL执行计划一模一样。所以优化器是进行了查询转换,将关联子查询转换成非关联子查询。

我们可以通过HINT让其不进行转换

SELECT /*+ NO_SEMI_GEN_CROSS OPTIMIZER_MODE(1) */ COUNT(*) FROM T1 A

WHERE A.ID IN (SELECT B.ID FROM T2 B);

执行计划如下:

1   #NSET2: [41, 1, 4]

2     #PRJT2: [41, 1, 4]; exp_num(1), is_atom(FALSE)

3       #AAGR2: [41, 1, 4]; grp_num(0), sfun_num(1) slave_empty(0)

4         #HASH LEFT SEMI JOIN2: [41, 100000, 4]; KEY_NUM(1);  KEY(A.ID=B.ID) KEY_NULL_EQU(0)

5           #CSCN2: [10, 100000, 4]; INDEX33555553(T1 as A)

6           #CSCN2: [10, 100000, 4]; INDEX33555554(T2 as B)

可以看到执行计划已经变了,先将T1,T2做全表扫描,然后进行HASH LEFT SEMI JOIN。连接条件是A.ID=B.ID。

SEMI_GEN_CROSS:优先采用半连接转换为等价的内连接,仅 OPTIMIZER_MODE=1 有效。

NO_SEMI_GEN_CROSS:不采用半连接转换为等价的内连接,仅 OPTIMIZER_MODE=1 有效。

那这两种那种效率更高呢。从执行时间来看第二种更快。

SELECT  COUNT(*) FROM T1 A WHERE A.ID IN (SELECT B.ID FROM T2 B);

 

SELECT /*+ NO_SEMI_GEN_CROSS * OPTIMIZER_MODE(1)*/ COUNT(*) FROM T1 A

WHERE A.ID IN (SELECT B.ID FROM T2 B);

 

如果我们将表数据库做成1000万。可以看到还是半连接的效率要好点。

SELECT  COUNT(*) FROM T1 A WHERE A.ID IN (SELECT B.ID FROM T2 B);

 

SELECT /*+ NO_SEMI_GEN_CROSS * OPTIMIZER_MODE(1)*/ COUNT(*) FROM T1 A

WHERE A.ID IN (SELECT B.ID FROM T2 B);

 

  1. 反连接

反连接返回左表中与右表不匹配的数据行,通常体现为 NOT EXISTS 或者 NOT IN 子查询。反连接的逻辑与半连接正好相反,示意图如下:

 

table1 中只有 id = 2 在 table2 中没有对应的数据,所以连接的结果返回了该记录。

反连接只会返回左表中的数据,右表只用于条件判断。反查询常见的应用包括:查找没有员工的部门信息,或者没有购买任何产品的顾客信息等。

SQL> EXPLAIN SELECT COUNT(*) FROM T1 A  WHERE A.ID NOT IN (SELECT B.ID FROM T2 B);

1   #NSET2: [4037, 1, 4]

2     #PRJT2: [4037, 1, 4]; exp_num(1), is_atom(FALSE)

3       #AAGR2: [4037, 1, 4]; grp_num(0), sfun_num(1) slave_empty(0)

4         #HASH LEFT SEMI JOIN2: [4037, 1, 4];  (ANTI),KEY_NUM(1);  KEY(A.ID=B.ID) KEY_NULL_EQU(0)

5           #CSCN2: [1057, 10000000, 4]; INDEX33555559(T1 as A)

6           #CSCN2: [1057, 10000000, 4]; INDEX33555560(T2 as B)

SQL> EXPLAIN SELECT  count(*) FROM T1 A

WHERE  NOT EXISTS(SELECT 1 FROM T2 B where A.ID=B.ID);2   

1   #NSET2: [4073, 1, 12]

2     #PRJT2: [4073, 1, 12]; exp_num(1), is_atom(FALSE)

3       #AAGR2: [4073, 1, 12]; grp_num(0), sfun_num(1) slave_empty(0)

4         #HASH LEFT SEMI JOIN2: [4073, 1, 12];  (ANTI),KEY_NUM(1);  KEY(A.ID=B.ID) KEY_NULL_EQU(0)

5           #CSCN2: [1073, 10000000, 12]; INDEX33555559(T1 as A)

6           #CSCN2: [1057, 10000000, 4]; INDEX33555560(T2 as B)

从执行计划来看,两种sql的执行计划完全一样。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 达梦数据库连接jar包是用于连接达梦数据库的Java开发工具包。在使用Java编程语言进行数据库开发时,我们需要使用相应的数据库连接驱动来实现与数据库的连接和操作。达梦数据库连接jar包提供了与达梦数据库进行连接的必要组件和接口。 达梦数据库连接jar包通常由达梦数据库厂商提供,可以从官方网站或其他可信的资源中下载。一般来说,使用达梦数据库连接jar包可以提供以下功能: 1. 连接数据库:通过调用相应的API,我们可以建立与达梦数据库的连接。这样我们就可以在Java程序中通过发送SQL语句来对数据库进行增删改查等操作。 2. 执行SQL语句:借助达梦数据库连接jar包,我们可以执行各种SQL语句,例如SELECT、INSERT、UPDATE等,以满足对数据库的需求。 3. 获取查询结果:通过执行SELECT语句,我们可以获得数据库查询的结果集。达梦数据库连接jar包提供了相应的API,方便我们从结果集中提取数据并进行处理。 4. 事务管理:达梦数据库连接jar包还支持事务管理的功能,可以确保多个数据库操作的一致性和完整性。 需要注意的是,在使用达梦数据库连接jar包之前,我们需要先将其添加到Java项目的classpath中,以便程序能够正常加载和使用相关的类和接口。 总之,达梦数据库连接jar包为开发者提供了连接和操作达梦数据库的基础功能。通过合理使用这些功能,我们能够更加便捷地进行Java数据库开发工作。 ### 回答2: 达梦数据库连接jar包是用于在Java程序中连接并操作达梦数据库的工具。通过引入达梦数据库连接jar包,我们可以通过Java程序与达梦数据库建立连接,进行数据的增删改查操作。 使用达梦数据库连接jar包连接达梦数据库的步骤如下: 1. 下载达梦数据库连接jar包,可以从达梦官方网站或其他可靠来源获取。 2. 将下载的jar包导入到Java项目中,可以将其放置在项目的lib文件夹下。 3. 在Java代码中引入所需的类和包,一般是通过import语句进行。 4. 通过代码创建一个数据库连接对象,使用连接对象建立与数据库的连接。可以使用提供的DriverManager.getConnection()方法,传入数据库连接字符串、用户名和密码等参数。 5. 执行数据库操作,如执行SQL语句来查询、插入、更新或删除数据。 6. 对于查询操作,可以使用ResultSet对象来获取查询结果。 7. 关闭数据库连接,释放资源。 使用达梦数据库连接jar包的好处是可以方便地在Java程序中集成达梦数据库的功能,使我们能够更轻松地操作和管理数据库。在实际使用中,需要根据具体需求选择合适的达梦数据库连接jar包版本,并根据文档中提供的方法和示例代码进行配置和使用。达梦数据库连接jar包提供了丰富的功能和API,能够满足我们的各种数据库操作需求。 ### 回答3: 达梦数据库(DMDB)是一种高性能的关系型数据库管理系统,它为用户提供了可靠的数据存储和管理服务。若要在Java应用程序中连接达梦数据库,需要使用相应的连接驱动jar包。 达梦数据库连接jar包是一个Java库文件,它包含了连接达梦数据库所需的类和方法。通过使用这个jar包,我们可以方便地在Java应用程序中建立与达梦数据库的连接,进行数据的读写操作。 为了使用达梦数据库连接jar包,首先需要下载该jar包,并将其添加到Java项目的类路径中。然后,我们可以使用Java代码来加载驱动程序、建立数据库连接以及执行SQL语句。 要加载驱动程序,我们可以使用Class.forName()方法来指定达梦数据库的驱动程序名称。接下来,我们可以使用DriverManager类的getConnection()方法来建立数据库连接,需要提供数据库URL、用户名和密码等连接信息。 一旦与达梦数据库建立了连接,我们就可以通过Connection对象来执行SQL语句。可以使用Statement或PreparedStatement接口的实现类来创建执行SQL语句的对象,然后可以调用其executeQuery()方法执行查询语句,或调用executeUpdate()方法执行更新语句。 执行完SQL语句后,可以使用ResultSet对象来获取查询结果,并通过遍历或特定方法来处理结果集中的数据。 需要注意的是,在使用达梦数据库连接jar包时,应该对连接资源进行适当的释放。可以通过调用close()方法关闭连接和释放资源,以避免因连接资源未释放而导致的内存泄漏和性能问题。 总之,达梦数据库连接jar包提供了在Java应用程序中连接达梦数据库的必要类和方法。通过合理使用这些类和方法,我们可以方便地连接达梦数据库,并进行相应的数据库操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值