优化SQL查询性能

时间:2018-11-16 16:27:41

标签: sql sql-server tsql

我正在进行查询,以在相关表格中查找某些值。假设我有一个表TableA和一堆其他表,这些表的外键都链接回了TableA。我想扫描所有这些相关的表,并检查是否存在至少1个具有这些值的记录。 我正在像下面的查询那样查询约7个表(1个表实际上可以包含超过1个将其关联回TableA的外键):

SELECT 
TableA.Field1,
TableA.Field2,
Table1Join.TableBPrimaryKey,
Table2Join.TableCPrimaryKey,
Table3Join.TableDPrimaryKey,
Table4Join.TableEPrimaryKey,
Table5Join.TableFPrimaryKey,
Table6Join.TableGPrimaryKey,
Table7Join.TableHPrimaryKey,
Table8Join.TableIPrimaryKey
/* As more JOINs are added below which result in more fields listed here in 
the SELECT statement, the query slows down by a lot. If I simply add JOIN’s 
without referencing their fields in the SELECT statement here, it runs fast 
*/
FROM
TableA 
/* Scan 1st related table */
INNER JOIN 
 (SELECT
      TableAAlias.PrimaryKey,
      MAX(TableB.PrimaryKey) AS TableBPrimaryKey
  FROM 
      TableA TableAAlias
  LEFT OUTER JOIN 
      TableB ON TableB.ForeignKey = TableAAlias.PrimaryKey
  GROUP BY 
      TableAAlias.PrimaryKey) AS Table1Join ON Table1Join.PrimaryKey = TableA.PrimaryKey
/* Scan 2nd related table */
INNER JOIN 
 (SELECT
     TableAAlias.PrimaryKey,
     MAX(TableC.PrimaryKey) AS TableBPrimaryKey
 FROM 
     TableA TableAAlias
 LEFT OUTER JOIN 
     TableC ON TableC.ForeignKey = TableAAlias.PrimaryKey
 GROUP BY 
     TableAAlias.PrimaryKey) AS Table2Join ON Table2Join.PrimaryKey = TableA.PrimaryKey
/* Scan 3rd related table */
INNER JOIN 
(SELECT
     TableAAlias.PrimaryKey,
     MAX(TableD.PrimaryKey) AS TableDPrimaryKey
 FROM 
     TableA TableAAlias
 LEFT OUTER JOIN 
     TableD ON TableD.ForeignKey = TableAAlias.PrimaryKey
 GROUP BY 
     TableAAlias.PrimaryKey) AS Table3Join ON Table3Join.PrimaryKey = TableA.PrimaryKey
/* Scan 4th related table */
INNER JOIN 
(SELECT
     TableAAlias.PrimaryKey,
     MAX(TableE.PrimaryKey) AS TableEPrimaryKey
 FROM 
     TableA TableAAlias
 LEFT OUTER JOIN 
     TableE ON TableE.ForeignKey = TableAAlias.PrimaryKey
 GROUP BY 
     TableAAlias.PrimaryKey) AS Table4Join ON Table4Join.PrimaryKey = TableA.PrimaryKey
/* Scan 5th related table */
INNER JOIN 
(SELECT
     TableAAlias.PrimaryKey,
     MAX(TableF.PrimaryKey) AS TableFPrimaryKey
 FROM 
     TableA TableAAlias
 LEFT OUTER JOIN 
     TableF ON TableF.ForeignKey = TableAAlias.PrimaryKey
 GROUP BY 
     TableAAlias.PrimaryKey) AS Table5Join ON Table5Join.PrimaryKey = TableA.PrimaryKey
/* Scan 6th related table */
INNER JOIN 
(SELECT
     TableAAlias.PrimaryKey,
     MAX(TableG.PrimaryKey) AS TableGPrimaryKey
 FROM 
     TableA TableAAlias
 LEFT OUTER JOIN 
     TableG ON TableG.ForeignKey = TableAAlias.PrimaryKey
 GROUP BY 
     TableAAlias.PrimaryKey) AS Table6Join ON Table6Join.PrimaryKey = TableA.PrimaryKey
/* Scan 7th related table */
INNER JOIN 
(SELECT
     TableAAlias.PrimaryKey,
     MAX(TableH.PrimaryKey) AS TableHPrimaryKey
 FROM 
     TableA TableAAlias
 LEFT OUTER JOIN 
     TableH ON TableH.ForeignKey = TableAAlias.PrimaryKey
 GROUP BY 
     TableAAlias.PrimaryKey) AS Table7Join ON Table7Join.PrimaryKey = TableA.PrimaryKey
/* Scan 8th related table */
INNER JOIN 
(SELECT
     TableAAlias.PrimaryKey,
     MAX(TableI.PrimaryKey) AS TableIPrimaryKey
 FROM 
     TableA TableAAlias
 LEFT OUTER JOIN 
     TableI ON TableI.ForeignKey = TableAAlias.PrimaryKey
 GROUP BY 
     TableAAlias.PrimaryKey) AS Table8Join ON Table8Join.PrimaryKey = TableA.PrimaryKey

这些表中的大多数包含超过100,000条记录。当我在主SELECT语句中不使用从联接派生的字段时,查询运行相对较快(约25秒)。当我使用某些字段时,它会运行大约相同的时间,但是当我添加从JOIN派生的更多字段时,查询将停止进行爬网,并且可能会运行数小时。这没有任何押韵或原因,因为我无法理解是什么原因造成的。我可以添加一个字段,然后它开始缓慢运行,然后删除它快速运行之前存在的另一个字段,并添加一个看似引起该问题的字段,然后再次快速运行。我当然可以将此查询分解为7个单独的查询,并创建一个临时表(我已经设法找到原因),在这种情况下它运行得相对较快,但是我不能使用临时表。我了解该查询可能未经过优化,但是我不是SQL专家,所以我不确定从哪里开始优化其性能。

1 个答案:

答案 0 :(得分:1)

与原始查询相比,该查询的效果如何?

["a", "b", "c", undefined, "x"]

NB:从共享的代码来看,这在功能上是相同的...如果问题中共享的代码与您的真实代码不匹配,则需要共享该代码以帮助我们进一步提供帮助。


每个评论更新

如果您只想通过某种方式显示任何表都包含与主表的关系,请尝试以下操作:

SELECT 
    TableA.Field1,
    TableA.Field2,
    (
        select MAX(TableB.PrimaryKey)
        from TableB
        where TableB.ForeignKey = TableA.PrimaryKey
    ) TableBPrimaryKey,
    (
        select MAX(TableC.PrimaryKey)
        from TableC
        where TableC.ForeignKey = TableA.PrimaryKey
    ) TableCPrimaryKey
FROM TableA 

另一种方法是:

Select TableA.*
, (

    select top 1 'TableB' from TableB where TableB.ForeignKey = TableA.PrimaryKey

    union all

    select top 1 'TableC' from TableC where TableC.ForeignKey = TableA.PrimaryKey

    --etc
) AnyTableHasValue --gives the name of the first table with a match  
From Table A