首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 计算机考试 > 认证考试 > JAVA认证 >

JAVA进阶:提高SQL性能的几种方法

2009-01-17 
提高SQL性能的几种方法

     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

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




 3COME考试频道为您精心整理,希望对您有所帮助,更多信息在http://www.reader8.com/exam/

热点排行