TSQL Join、查询处理顺序和存储

Posted

技术标签:

【中文标题】TSQL Join、查询处理顺序和存储【英文标题】:TSQL Join, Query Processing order and storage 【发布时间】:2016-05-14 17:02:51 【问题描述】:

表结构:

CREATE TABLE dbo.Transactions
(
    actid INT NOT NULL, --Account ID
    tranid INT NOT NULL,  -- Transaction ID
    val MONEY NOT NULL, --- Transaction value

    CONSTRAINT PK_Transactions PRIMARY KEY(actid, tranid)
);

以下低效查询尝试确定每次交易后的运行余额

SELECT 
    T1.actid, T1.tranid, T1.val,
    SUM(T2.val) AS balance
FROM 
    dbo.Transactions AS T1
JOIN 
    dbo.Transactions AS T2 ON T2.actid = T1.actid
                           AND T2.tranid <= T1.tranid
GROUP BY 
    T1.actid, T1.tranid, T1.val;

我不确定在查询中是如何处理连接的。连接是否被视为子查询,对于每个组 (T1.actid, T1.tranid, T1.val) 执行连接语句?这是否意味着如果有 10K Transactions ,则此查询会创建 10K 连接数据集?

【问题讨论】:

【参考方案1】:

在 SSMS 中执行您的查询。然后突出显示它并按 Ctrl + L 以查看执行计划。这将向您展示 SQL Server 计划如何执行查询,有时还会建议索引等。

【讨论】:

【参考方案2】:

这意味着您将拥有连接满足的确切行数

处理 T1 中的每一行,并从 T2 中引入满足连接条件的行。

连接可以被处理为循环、散列或合并。通常优化器不使用哈希。

最好的办法就是运行它。输出应该讲述一个故事。

【讨论】:

【参考方案3】:

了解的唯一方法是“研究”查询计划。

仅供参考:在我看来,您的查询相当于

SELECT 
    T1.actid, T1.tranid, T1.val,
    balance = (SELECT SUM(T2.val)
                 FROM dbo.Transactions
                WHERE T2.actid = T1.actid
                  AND T2.tranid <= T1.tranid)
FROM 
    dbo.Transactions AS T1

说实话,我更喜欢“这个”版本,因为它对我来说更具可读性;我还希望这个版本稍微“精简”,因为对排序的需求较少,但只有实际测试才能说明问题。有时看到优化器在幕后做了什么令人惊讶!再次显示查询计划。

因此,运行两个查询并比较生成的查询计划,这些应该让您了解它们的相对成本。现在,请记住,“成本”并不总是与“时间”直接相关。所以你可能想检查哪一个在你的硬件上和“典型负载”下运行得更快;还要记住,例如缓存可能会在这里产生影响!

【讨论】:

以上是关于TSQL Join、查询处理顺序和存储的主要内容,如果未能解决你的问题,请参考以下文章

数据库工程开发秘籍之TSQL 存储过程user stored procedure的概念与案例实战

表连接Tsql基本编程和存储过程

MySQL逻辑架构存储引擎和SQL预热 --MySQL高级篇1

查询中的 TSQL 顺序/序列组

TSQL - 加入表的正确顺序是啥?

TSQL NOLOCK VIEW 和存储过程