注册
达梦数据库连接算子解析
技术分享/ 文章详情 /

达梦数据库连接算子解析

LHX 2025/12/12 62 2 0

达梦数据库连接算子解析

在达梦数据库的查询优化过程中,连接算子的选择对查询性能有着决定性影响。本文将详细介绍达梦数据库中常用的连接算子,包括其工作原理、典型用例及优化建议,帮助大家更加深入的理解达梦JOIN算子。

达梦数据库的连接算子主要分为嵌套循环连接(NEST LOOP JOIN)、哈希连接(HASH JOIN)、归并连接(MERGE JOIN) 和索引连接(INDEX JOIN) 四大类,各类算子针对不同数据场景设计,核心功能差异显著。

一、连接算子说明

达梦数据库的连接算子主要分为嵌套循环连接(NEST LOOP JOIN)、哈希连接(HASH JOIN)、归并连接(MERGE JOIN) 和索引连接(INDEX JOIN) 四大类,各类算子针对不同数据场景设计,核心功能差异显著。

(一)嵌套循环连接类(NEST LOOP)

嵌套循环连接通过 “外层表遍历 + 内层表匹配” 的方式实现连接,适用于小表连接或被驱动表表有高效索引的场景,核心优势是资源开销消耗低、支持非等值连接、执行逻辑简单等。

(1)NEST LOOP INDEX JOIN2:索引内连接,被驱动表通过索引快速查找匹配数据,仅返回两表匹配的记录,依赖内层表的连接列索引提升查找效率。

    u.username,
    SUM(o.amount) AS total_amount
FROM 
    users u
JOIN 
    orders o ON u.user_id = o.user_id
GROUP BY 
    u.user_id, u.username;

image.png
(2)NEST LOOP FULL JOIN2:嵌套循环全外连接,驱动表逐行扫描,被驱动表针对每行数据进行匹配查询,返回两个表中所有匹配与不匹配的记录,无论是否找到关联数据,两端表的记录都会保留,通过嵌套循环逻辑处理全外连接的补全逻辑。

    e.emp_name,
    d.dept_name,
    d.location AS
FROM employees e
FULL JOIN departments d 
    ON e.dept_id = d.dept_id
ORDER BY e.emp_id;

image.png
(3)NEST LOOP INNER JOIN2:基础嵌套循环内连接,仅保留两表中满足连接条件的记录。

SELECT /*+ USE_NL(d, e) */ 
    d.dept_name, 
    COUNT(e.emp_id) as emp_count
FROM departments_nl d
INNER JOIN employees_nl e ON d.dept_id = e.dept_id
GROUP BY d.dept_name
ORDER BY emp_count DESC;

image.png
(4)NEST LOOP LEFT JOIN2:嵌套循环左外连接,保留左表所有记录。

SELECT d.dept_name, 
       p.project_name,
       COALESCE(p.start_date, '无项目') as project_start
FROM departments d
LEFT JOIN projects p ON d.dept_id = p.dept_id 
                   AND p.start_date >= '2024-01-01';

image.png
(5)NEST LOOP SEMI JOIN2:嵌套循环半连接,仅返回左表中存在匹配右表记录的行。

SELECT d.dept_id, d.dept_name
FROM departments d
WHERE EXISTS (
    SELECT 1 FROM projects p
    WHERE p.dept_id = d.dept_id
);

image.png

(二)哈希连接类(HASH JOIN)

哈希连接通过 “构建哈希表 + 探测匹配” 的逻辑实现连接,适用于大表连接或无有效索引的场景,核心优势是处理大量数据时效率稳定。
(1)HASH FULL JOIN2:哈希全外连接。

    CASE 
        WHEN d.dept_id IS NULL THEN '缺失部门:员工无对应部门'
        WHEN e.emp_id IS NULL THEN '缺失员工:部门无对应员工'
        ELSE '正常匹配'
    END as 检查结果,
    d.dept_id,
    d.dept_name,
    e.emp_id,
    e.emp_name
FROM departments d
FULL OUTER JOIN employees e ON d.dept_id = e.dept_id
WHERE d.dept_id IS NULL OR e.emp_id IS NULL
ORDER BY 检查结果, d.dept_id, e.emp_id;

image.png
(2)HASH LEFT JOIN2:哈希左外连接。

SELECT d.dept_id, d.dept_name, e.emp_name, e.salary
FROM departments_hash d
LEFT JOIN employees_hash e ON d.dept_id = e.dept_id
WHERE d.budget > 200000;

image.png
(3)HASH LEFT SEMI MULTIPLE JOIN:达梦数据库处理多列NOT IN 时的算子。当子查询返回多列,且无法用索引时,优化器会用哈希表暴力匹配,但保留主表所有行。

SELECT p.product_name, p.category, p.price
FROM products p
WHERE (p.product_id, p.create_date) NOT IN (
    SELECT o.product_id, o.order_date
    FROM orders o
    WHERE o.quantity >= 2  
    AND o.order_date >= '2024-01-01' 
);

image.png
(4)HASH LEFT SEMI JOIN2:哈希左半连接。

    '部门' as 来源,
    d.dept_id as 部门ID,
    d.dept_name as 部门名称,
    NULL as 员工ID,
    NULL as 员工姓名
FROM departments d
WHERE NOT EXISTS (
    SELECT 1 FROM employees e 
    WHERE e.dept_id = d.dept_id
)

image.png
(5)HASH2 INNER JOIN:哈希内连接。

    '匹配' as 来源,
    d.dept_id as 部门ID,
    d.dept_name as 部门名称,
    e.emp_id as 员工ID,
    e.emp_name as 员工姓名
FROM departments d
INNER JOIN employees e ON d.dept_id = e.dept_id

image.png

(三)归并连接类(MERGE JOIN)

归并连接需先对两个表的连接列排序,再通过已排序后的数据实现有效数据范围内匹配,适用于连接列已排序或需排序输出的场景,核心优势是排序后匹配效率极高,且结果天然有序。
(1)MERGE INNER JOIN3:归并内连接,先对两表连接列分别排序(若已排序则跳过),再同步扫描两个有序表,当连接列值相等时返回匹配记录,适用于需要有序结果的大表连接。

SELECT 
       /*+ USE_MERGE(T1,T2) */ 
       * 
  FROM T1, 
       T2 
 WHERE T1.ID = T2.ID 
   AND T1.ID < 1 
   AND T2.ID < 1;

image.png
(2)MERGE SEMI JOIN3:归并半连接,仅返回左表中存在右表匹配记录的行,且结果保持左表排序顺序,适用于需有序输出的半连接场景。

SELECT 
  /*+ USE_MERGE_SEMI(T1, T2) */ 
  T1.*
FROM T1
WHERE T1.ID IN (SELECT T2.ID FROM T2)
  AND T1.ID < 1;

image.png

(四)索引连接类(INDEX JOIN)

索引连接直接利用表的索引完成连接,无需扫描全表,适用于连接列有高质量索引的场景,核心优势是查询延迟低、IO 消耗小。
(1)INDEX JOIN LEFT JOIN2:索引左外连接,左表扫描过程中,通过右表连接列的索引快速查找匹配数据,保留左表所有记录,避免右表全表扫描。

SELECT p.product_name, p.category, p.price
FROM products p
LEFT JOIN orders o 
    ON p.product_id = o.product_id 
    AND o.quantity >= 2 
    AND o.order_date BETWEEN '2024-01-01' AND '2024-02-28'
ORDER BY p.price DESC;

image.png
(2)INDEX JOIN SEMI JOIN2:索引半连接,左表逐行扫描时,通过右表索引判断是否存在匹配记录,仅返回左表中存在匹配的行,索引查找替代右表全表扫描,效率显著提升。

SELECT p.product_name, p.category, p.price, o.product_id
FROM products p
WHERE p.product_id IN (
    SELECT o.product_id 
    FROM orders o 
    WHERE o.quantity >= 2
    AND o.order_date BETWEEN '2024-01-01' AND '2024-02-28'
)
ORDER BY p.price DESC;

image.png

二、算子特性

image.png

三、优化器提示更改join算子类型:

在达梦数据库进行数据关联时,若优化器选择的JOIN算子执行代价过高,可通过优化器提示(HINT)来调整连接策略。以下是常用的收集统计信息、HINT示例:

STAT 100 ON T1(ID);

--使用hash join进行关联
SELECT /*+ USE_HASH(a b) */ * FROM table1 a JOIN table2 b ...;


--当连接情况为左表+右表索引时,强制两个表间使用nestloop index join进行关联
SELECT /*+ USE_NL_WITH_INDEX(a b) */ * FROM table1 a JOIN table2 b ...; 


--使用merge join进行关联
SELECT /*+ USE_MERGE(a b) */ * FROM table1 a JOIN table2 b ...;

本文如有疏漏或不准确之处,敬请批评指正。

评论
后发表回复

作者

文章

阅读量

获赞

扫一扫
联系客服