簡體   English   中英

是否可以提高具有不同連接和多個連接的查詢的性能?

[英]Is it possible to improve the performance of query with distinct and multiple joins?

有以下查詢:

SELECT DISTINCT ID, ACCOUNT,
   CASE
       WHEN p.GeneralLevel = '1' THEN '1'
       WHEN p.Level3 IS NULL THEN '2'
       WHEN p.Level4 IS NULL THEN '3'
       WHEN p.Level5 IS NULL THEN '4'
       WHEN p.Level6 IS NULL THEN '5'
       WHEN p.Level7 IS NULL THEN '6'
       WHEN p.Level8 IS NULL THEN '7'
       ELSE '8'
   END AS LEVEL,
   CASE
       WHEN c.codeValueDescription IS NULL THEN p.Level2
       ELSE c.codeValueDescription
   END AS L2_CODE,
   CASE
       WHEN d.codeValueDescription IS NULL THEN p.Level3
       ELSE d.codeValueDescription
   END AS L3_CODE,
   CASE
       WHEN j.codeValueDescription IS NULL THEN p.Level4
       ELSE j.codeValueDescription
   END AS L4_CODE,
   CASE
       WHEN f.codeValueDescription IS NULL THEN p.Level5
       ELSE f.codeValueDescription
   END AS L5_CODE,
   CASE
       WHEN g.codeValueDescription IS NULL THEN p.Level6
       ELSE g.codeValueDescription
   END AS L6_CODE,
   CASE
       WHEN h.codeValueDescription IS NULL THEN p.Level7
       ELSE h.codeValueDescription
   END AS L7_CODE,
   p.Level8
   FROM generic p
   LEFT JOIN
     (SELECT codeValue, codeValueDescription
      FROM codes
      WHERE code = '2') c ON p.Level2 = c.codeValue
   LEFT JOIN
     (SELECT codeValue, codeValueDescription
      FROM codes
      WHERE code = '3') d ON p.Level3 = d.codeValue
   LEFT JOIN
     (SELECT codeValue, codeValueDescription
      FROM codes
      WHERE code = '4') j ON p.Level4 = j.codeValue
   LEFT JOIN
     (SELECT codeValue, codeValueDescription
      FROM codes
      WHERE code = '5') f ON p.Level5 = f.codeValue
   LEFT JOIN
     (SELECT codeValue, codeValueDescription
      FROM codes
      WHERE code = '3') g ON p.Level6 = g.codeValue //yes, code is 3 again
   LEFT JOIN
     (SELECT codeValue, codeValueDescription
      FROM codes
      WHERE code = '3') h ON p.Level7 = h.codeValue //and yes, again code 3 here

“通用”表的某些列(排除日期和其他對我們來說不重要的列):

ID INTEGER NOT NULL,
ACCOUNT VARCHAR(50) NOT NULL,
GeneralLevel1 VARCHAR(50),
Level2 VARCHAR(50),
Level3 VARCHAR(50),
Level4 VARCHAR(50),
Level5 VARCHAR(50),
Level6 VARCHAR(50),
Level7 VARCHAR(50),
Level8 VARCHAR(50)

簡單數據:

ID,ACCOUNT_ID,LEVEL_1,LEVEL_2,...LEVEL_8
id1,ACCOUNT_ID1,GENERAL,null,...null
id1,ACCOUNT_ID2,GENERAL,A,...null
id1,ACCOUNT_ID2,GENERAL,B,...null
id2,ACCOUNT_ID1,GENERAL,null,...null
id2,ACCOUNT_ID2,GENERAL,A,...null
id2,ACCOUNT_ID3,GENERAL,B,...H

當前查詢運行時間超過 1 秒,通常返回 100 到 1000 條記錄,我想提高此查詢的性能。 想法是擺脫這些 LEFT JOINS 並以某種方式重寫此查詢以提高性能。

也許有辦法改進此查詢以更快地獲取數據? 我希望我在這里提供了足夠的信息。 數據庫是自定義的,引擎蓋下的 NO_SQL 巨人,但我們數據庫橋的語法與 MySQL 非常相似。不幸的是,我無法提供此查詢的執行計划,因為它在服務器端處理,然后生成一些我無法擁有的 SQL一個訪問。

您正在從codes表中進行鍵/值查找。 您的查詢包含其中幾個 LEFT JOIN 模式。

   FROM generic p
   LEFT JOIN
     (SELECT codeValue, codeValueDescription
      FROM codes
      WHERE code = '2') c ON p.Level2 = c.codeValue
   LEFT JOIN
     (SELECT codeValue, codeValueDescription
      FROM codes
      WHERE code = '3') d ON p.Level3 = d.codeValue

可以重構這些 LEFT JOIN 以消除子查詢。 此重構可能會更清楚地向 SQL 系統發出您的意圖信號。 結果看起來像這樣。

   FROM generic p
   LEFT JOIN codes c ON  p.Level2 = c.codeValue AND c.code = '2'
   LEFT JOIN codes d ON  p.Level3 = d.codeValue AND d.code = '3'

如果您的 SQL 系統允許索引,那么codes表上的覆蓋索引將有助於加快您的鍵/值查找。

ALTER TABLE codes ADD INDEX (codeValue, code, codeValueDescription)

您的 SELECT 子句包含很多此類內容:

   CASE
       WHEN c.codeValueDescription IS NULL THEN p.Level2
       ELSE c.codeValueDescription
   END AS L2_CODE,
   CASE
       WHEN d.codeValueDescription IS NULL THEN p.Level3
       ELSE d.codeValueDescription
   END AS L3_CODE

它可能沒有多大幫助,但這可以通過將其重寫為來簡化

   COALESCE(c.codeValueDescription, p.Level2) AS L2_CODE,
   COALESCE(d.codeValueDescription, p.Level3) AS L3_CODE

如果刪除DISTINCT限定符會怎樣? 這可能需要一些處理時間。 如果您的generic.ID列是主鍵,那么DISTINCT對您一點好處都沒有:這些列值不會重復。 (大多數現代 SQL 查詢規划器檢測到這種情況並跳過重復數據刪除步驟,但我們不知道您的查詢規划器有多現代。)

您的查詢不包含整體WHERE子句,因此它必須處理generic表中的每一行。 而且,如果該表很大,您的結果集也會很大。 我相信您知道,掃描整個大表需要時間和資源。

綜上所述,通過 SQL 網橋進行這樣的查詢,每行一毫秒並不是確鑿證據的可怕性能。 你可能不得不忍受它。 另一種方法可能是將代碼應用於應用程序中的數據:吞噬整個codes表,然后編寫一些應用程序邏輯來執行 CASE / WHEN / THEN 或 COALESCE 工作。 換句話說,將 LEFT JOIN 操作移至您的應用程序。 如果您的 SQL 網橋能夠快速處理簡單的SELECT * FROM generic單表查詢,這將有很大幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM