溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

如何提高SQL語句的性能

發(fā)布時間:2022-01-15 09:57:37 來源:億速云 閱讀:207 作者:小新 欄目:數(shù)據(jù)庫

小編給大家分享一下如何提高SQL語句的性能,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

  1, 從 INSERT 返回 IDENTITY

  SELECT @@IDENTITY

  2, 內(nèi)嵌視圖與臨時表

  臨時表 - 在 tempdb 中的臨時表會導(dǎo)致查詢進(jìn)行大量 I/O 操作和磁盤訪問,臨時表會消耗大量資源。

  內(nèi)嵌視圖 -使用內(nèi)嵌視圖取代臨時表。內(nèi)嵌視圖只是一個可以聯(lián)接到 FROM 子句中的查詢。如果只需要將數(shù)據(jù)聯(lián)接到其他查詢,則可以試試使用內(nèi)嵌視圖,以節(jié)省資源。

  3, 避免 LEFT JOIN 和 NULL

  LEFT JOIN 消耗的資源非常之多,因為它們包含與 NULL(不存在)數(shù)據(jù)匹配的數(shù)據(jù)。在某些情況下,這是不可避免的,但是代價可能非常高。LEFT JOIN 比 INNER JOIN 消耗資源更多,所以如果您可以重新編寫查詢以使得該查詢不使用任何 LEFT JOIN,則會得到非??捎^的回報。

  加快使用 LEFT JOIN 的查詢速度的一項技術(shù)涉及創(chuàng)建一個 TABLE 數(shù)據(jù)類型,插入第一個表(LEFT JOIN 左側(cè)的表)中的所有行,然后使用第二個表中的值更新 TABLE 數(shù)據(jù)類型。此技術(shù)是一個兩步的過程,但與標(biāo)準(zhǔn)的 LEFT JOIN 相比,可以節(jié)省大量時間。一個很好的規(guī)則是嘗試各種不同的技術(shù)并記錄每種技術(shù)所需的時間,直到獲得用于您的應(yīng)用程序的執(zhí)行性能最佳的查詢。

  DECLARE @tblMonths TABLE (sMonth VARCHAR(7))

  4, 靈活使用笛卡爾乘積

  對于此技巧,我將進(jìn)行非常詳細(xì)的介紹,并提倡在某些情況下使用笛卡爾乘積。出于某些原因,笛卡爾乘積 (CROSS JOIN) 遭到了很多譴責(zé),開發(fā)人員通常會被警告根本就不要使用它們。在許多情況下,它們消耗的資源太多,從而無法高效使用。但是像 SQL 中的任何工具一樣,如果正確使用,它們也會很有價值。

  其中一段示例代碼,值得效仿:

  -- 笛卡爾乘積則可以返回所有月份的所有客戶。笛卡爾乘積基本上是將第一個表與第二個表相乘,生成一個行集合,其中包含第一個表中的行數(shù)與第二個表中的行數(shù)相乘的結(jié)果。因此,笛卡爾乘積會向表 @tblFinal 返回 12(所有月份)*81(所有客戶)=972 行。最后的步驟是使用此日期范圍內(nèi)每個客戶的月銷售額總計更新 @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, 拾遺補(bǔ)零   

這里介紹其他一些可幫助提高 SQL 查詢效率的常用技術(shù)。假設(shè)您將按區(qū)域?qū)λ袖N售人員進(jìn)行分組并將他們的銷售額進(jìn)行小計,但是您只想要那些數(shù)據(jù)庫中標(biāo)記為處于活動狀態(tài)的銷售人員。您可以按區(qū)域?qū)︿N售人員分組,并使用 HAVING 子句消除那些未處于活動狀態(tài)的銷售人員,也可以在 WHERE 子句中執(zhí)行此操作。在 WHERE 子句中執(zhí)行此操作會減少需要分組的行數(shù),所以比在 HAVING 子句中執(zhí)行此操作效率更高。HAVING 子句中基于行的條件的篩選會強(qiáng)制查詢對那些在 WHERE 子句中會被去除的數(shù)據(jù)進(jìn)行分組。   

另一個提高效率的技巧是使用 DISTINCT 關(guān)鍵字查找數(shù)據(jù)行的單獨報表,來代替使用 GROUP BY 子句。在這種情況下,使用 DISTINCT 關(guān)鍵字的 SQL 效率更高。請在需要計算聚合函數(shù)(SUM、COUNT、MAX 等)的情況下再使用 GROUP BY。另外,如果您的查詢總是自己返回一個唯一的行,則不要使用 DISTINCT 關(guān)鍵字。在這種情況下,DISTINCT 關(guān)鍵字只會增加系統(tǒng)開銷。   

以上是“如何提高SQL語句的性能”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學(xué)習(xí)更多知識,歡迎關(guān)注億速云行業(yè)資訊頻道!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

sql
AI