`
kang275284
  • 浏览: 165328 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

五种提高 SQL 性能的方法

阅读更多
本文节选自MSDN的文章《五种提高 SQL 性能的方法》,提出如何提高基于SQL Server应用程序的运行效率,非常值得推荐。对一些Traffic很高的应用系统而言,如何提高和改进SQL指令,是非常重要的,也是一个很好的突破点。
*文章主要包括如下一些内容(如感兴趣,请直接访问下面的URL阅读完整的中英文文档):

1, 从 INSERT 返回 IDENTITY 
SELECT @@IDENTITY

2, 内嵌视图与临时表 
临时表 - 在 tempdb 中的临时表会导致查询进行大量 I/O 操作和磁盘访问,临时表会消耗大量资源。
内嵌视图 -使用内嵌视图取代临时表。内嵌视图只是一个可以联接到 FROM 子句中的查询。如果只需要将数据联接到其他查询,则可以试试使用内嵌视图,以节省资源。

3, 避免 LEFT JOIN 和 NULL 
LEFT JOIN 消耗的资源非常之多,因为它们包含与 NULL(不存在)数据匹配的数据。在某些情况下,这是不可避免的,但是代价可能非常高。LEFT JOIN 比 INNER JOIN 消耗资源更多,所以如果您可以重新编写查询以使得该查询不使用任何 LEFT JOIN,则会得到非常可观的回报。

加快使用 LEFT JOIN 的查询速度的一项技术涉及创建一个 TABLE 数据类型,插入第一个表(LEFT JOIN 左侧的表)中的所有行,然后使用第二个表中的值更新 TABLE 数据类型。此技术是一个两步的过程,但与标准的 LEFT JOIN 相比,可以节省大量时间。一个很好的规则是尝试各种不同的技术并记录每种技术所需的时间,直到获得用于您的应用程序的执行性能最佳的查询。
DECLARE @tblMonths TABLE (sMonth VARCHAR(7))

4, 灵活使用笛卡尔乘积 
对于此技巧,我将进行非常详细的介绍,并提倡在某些情况下使用笛卡尔乘积。出于某些原因,笛卡尔乘积 (CROSS JOIN) 遭到了很多谴责,开发人员通常会被警告根本就不要使用它们。在许多情况下,它们消耗的资源太多,从而无法高效使用。但是像 SQL 中的任何工具一样,如果正确使用,它们也会很有价值。

其中一段示例代码,值得效仿:
-- 笛卡尔乘积则可以返回所有月份的所有客户。笛卡尔乘积基本上是将第一个表与第二个表相乘,生成一个行集合,其中包含第一个表中的行数与第二个表中的行数相乘的结果。因此,笛卡尔乘积会向表 @tblFinal 返回 12(所有月份)*81(所有客户)=972 行。最后的步骤是使用此日期范围内每个客户的月销售额总计更新 @tblFinal 表,以及选择最终的行集。

DECLARE @tblMonths TABLE (sMonth VARCHAR(7))
DECLARE @tblCustomers TABLE (    CustomerID CHAR(10),
            CompanyName VARCHAR(50),
            ContactName VARCHAR(50))
DECLARE @tblFinal TABLE (    sMonth VARCHAR(7),
            CustomerID CHAR(10),
            CompanyName VARCHAR(50),
            ContactName VARCHAR(50),
            mSales MONEY)


DECLARE @dtStartDate DATETIME,
    @dtEndDate DATETIME,
    @dtDate DATETIME,
    @i INTEGER

SET @dtEndDate = '5/5/1997'

SET @dtEndDate = DATEADD(DD, -1, CAST(CAST((MONTH(@dtEndDate) + 1) AS   
    VARCHAR(2)) + '/01/' + CAST(YEAR(@dtEndDate) AS VARCHAR(4)) + ' 23:59:59' AS DATETIME))
SET @dtStartDate = DATEADD(MM, -1 * 12, @dtEndDate)


-- Get all months into the first table
SET @i = 0
WHILE (@i < 12)
BEGIN
    SET @dtDate = DATEADD(mm, -1 * @i, @dtEndDate)
    INSERT INTO @tblMonths SELECT CAST(YEAR(@dtDate) AS VARCHAR(4)) + '-' +
                CASE
                WHEN MONTH(@dtDate) < 10
                    THEN '0' + CAST(MONTH(@dtDate) AS VARCHAR(2))
                ELSE CAST(MONTH(@dtDate) AS VARCHAR(2))
                END AS sMonth
    SET @i = @i + 1
END

-- Get all clients who had sales during that period into the "y" table
INSERT INTO @tblCustomers
    SELECT    DISTINCT
        c.CustomerID,
        c.CompanyName,
        c.ContactName
    FROM Customers c
        INNER JOIN Orders o ON c.CustomerID = o.CustomerID
    WHERE    o.OrderDate BETWEEN @dtStartDate AND @dtEndDate

INSERT INTO @tblFinal
SELECT    m.sMonth,
    c.CustomerID,
    c.CompanyName,
    c.ContactName,
    0
FROM @tblMonths m CROSS JOIN @tblCustomers c

UPDATE @tblFinal  SET
    mSales = mydata.mSales
FROM @tblFinal f INNER JOIN
    (
    SELECT    c.CustomerID,
        CAST(YEAR(o.OrderDate) AS VARCHAR(4)) + '-' +
        CASE WHEN MONTH(o.OrderDate) < 10
            THEN '0' + CAST(MONTH(o.OrderDate) AS VARCHAR(2))
            ELSE CAST(MONTH(o.OrderDate) AS VARCHAR(2))
        END AS sMonth,
        SUM(od.Quantity * od.UnitPrice) AS mSales
    FROM Customers c
        INNER JOIN Orders o ON c.CustomerID = o.CustomerID
        INNER JOIN [Order Details] od ON o.OrderID = od.OrderID
    WHERE    o.OrderDate BETWEEN @dtStartDate AND @dtEndDate
    GROUP BY
        c.CustomerID,
        CAST(YEAR(o.OrderDate) AS VARCHAR(4)) + '-' +
        CASE WHEN MONTH(o.OrderDate) < 10
            THEN '0' + CAST(MONTH(o.OrderDate) AS VARCHAR(2))
            ELSE CAST(MONTH(o.OrderDate) AS VARCHAR(2))
        END
    ) mydata on f.CustomerID = mydata.CustomerID AND f.sMonth =
       mydata.sMonth


SELECT    f.sMonth,
    f.CustomerID,
    f.CompanyName,
    f.ContactName,
    f.mSales
FROM @tblFinal f
ORDER BY
    f.CompanyName,
    f.sMonth


5, 拾遗补零 
这里介绍其他一些可帮助提高 SQL 查询效率的常用技术。假设您将按区域对所有销售人员进行分组并将他们的销售额进行小计,但是您只想要那些数据库中标记为处于活动状态的销售人员。您可以按区域对销售人员分组,并使用 HAVING 子句消除那些未处于活动状态的销售人员,也可以在 WHERE 子句中执行此操作。在 WHERE 子句中执行此操作会减少需要分组的行数,所以比在 HAVING 子句中执行此操作效率更高。HAVING 子句中基于行的条件的筛选会强制查询对那些在 WHERE 子句中会被去除的数据进行分组。

另一个提高效率的技巧是使用 DISTINCT 关键字查找数据行的单独报表,来代替使用 GROUP BY 子句。在这种情况下,使用 DISTINCT 关键字的 SQL 效率更高。请在需要计算聚合函数(SUM、COUNT、MAX 等)的情况下再使用 GROUP BY。另外,如果您的查询总是自己返回一个唯一的行,则不要使用 DISTINCT 关键字。在这种情况下,DISTINCT 关键字只会增加系统开销。 

分享到:
评论

相关推荐

    五种提高 SQL 性能的方法总结

    ### 五种提高 SQL 性能的方法总结 在日常的数据库操作中,为了提升应用程序的运行速度,有时候仅仅需要对 SQL 查询进行一些细微的优化就能达到显著的效果。本文将详细介绍五种有效提升 SQL 性能的方法,帮助你在...

    五种提高SQL性能的方法

    【提高SQL性能的方法】 在数据库开发中,优化SQL性能至关重要,因为它直接影响到应用程序的响应速度和用户体验。这里介绍五种有效提升SQL性能的方法,这些方法是基于实际开发经验总结得出的。 1. **从INSERT返回...

    五种提高SQL性能的方法.doc

    【提高SQL性能】 在数据库管理系统中,SQL性能优化对于提升应用程序的整体效率至关重要。当SQL查询执行缓慢,导致用户等待时间过长时,就需要采取措施进行优化。以下五种方法可以帮助提升SQL性能: 1. **从INSERT...

    五种提高 SQL 性能的方法.doc

    在SQL性能优化中,有五种关键方法可以帮助改善查询效率,从而提高数据库系统的整体性能。以下将详细讨论这些方法: 1. **索引优化**:索引是数据库中用于快速查找记录的关键数据结构。创建合适的索引可以显著提高...

    如何提高sql性能

    ### 如何提高SQL性能 #### 一、理解Oracle体系结构的重要性 在探讨如何提高SQL性能之前,我们首先需要深入理解Oracle数据库的体系结构。Oracle数据库的体系结构是其高效运行的基础,也是进行性能优化的关键所在。...

    提高SQL性能的方法

    迟早您会遇到这种情况:应用程序中的 SQL 查询不能按照您想要的方式进行响应。它要么不返回数据,要么耗费的时间长得出奇。如果它降低了报告或您的企业应用程序的速度,用户必须等待的时间过长,他们就会很不满意。...

    DB2 SQL性能调优秘笈

    索引对于提高SQL查询性能至关重要。合理设计和维护索引可以显著加快查询速度。以下是一些实用的索引策略: 1. **复合索引选择**:当多个列经常被一起用作查询条件时,创建一个包含这些列的复合索引可以显著提高查询...

    ORACLE SQL性能优化系列

    ORACLE SQL性能优化系列 ORACLE SQL性能优化是数据库管理员和开发者非常关心的一个话题。为了提高数据库的性能,ORACLE 提供了多种优化技术。下面我们将详细介绍 ORACLE SQL 性能优化系列中的一些重要知识点。 一...

Global site tag (gtag.js) - Google Analytics