查询自联接表似乎很慢

时间:2016-02-09 00:36:05

标签: sql sql-server

我有一个表格,其中包含一个分层的位置列表。位置具有父位置,并且位置具有多个兄弟位置。

CREATE TABLE [dbo].[Location]
(
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [ParentID] [int] NULL,
    [LocationTypeID] [int] NOT NULL,
    [Description] [varchar](100) NOT NULL,
    [Deleted] [datetime] NULL,
    [CreatedDate] [datetime] NOT NULL,
    [CreatedUserID] [int] NOT NULL,
    [ModifiedDate] [datetime] NULL,
    [ModifiedUserID] [int] NULL,
    [Version] [timestamp] NOT NULL,

    CONSTRAINT [pk_location] 
    PRIMARY KEY CLUSTERED ([ID] ASC)
            WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,  
                  IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, 
                  ALLOW_PAGE_LOCKS = ON) 
) 
GO

ALTER TABLE [dbo].[Location] WITH CHECK 
   ADD CONSTRAINT [fk_location_location] 
   FOREIGN KEY([ParentID]) REFERENCES [dbo].[Location] ([ID])
GO

当我查询数据时,我创建了一个简化输出的视图:

WITH MyLocation AS 
( 
    SELECT 
        A.ParentID, A.ID,
        Description,
        0 AS 'Level',
        CAST(A.Description AS VARCHAR(512)) AS SORT_PATH
    FROM     
        Location A
    WHERE    
        A.ParentID IS NULL

    UNION ALL

    SELECT 
        C.ParentID, C.ID,
        C.Description,
        Level + 1,
        CAST(SORT_PATH + '//' + C.Description AS VARCHAR(512)) AS SORT_PATH
    FROM 
        Location C
    INNER JOIN 
        MyLocation ON MyLocation.ID = C.ParentID
)
SELECT  
    ParentID, ID, Level,
    SORT_PATH,
    ML.Description AS DISPLAY_PATH
FROM   
    MyLocation AS ML 

然后我从这个视图中选择,例如:

SELECT * 
FROM MyView 
WHERE ID = 367

我的响应时间大约为400毫秒,表格只有750行。这可能是由于查询需要查看整个数据负载,然后只选择我想要的项目,但速度似乎仍然有点慢。

是否有一些索引可用于改善性能?

以下是执行计划。有一个成本高达55%的成本聚簇索引扫描......并且发生了大约29%的连接事件。这些可以通过添加索引来辅助吗?也许删除无效的'ParentID'(表示根)?

enter image description here

我使用以下代码在ParentID上添加了一个新索引:

CREATE INDEX ix_location_parentids
ON Location (ParentID)

平均执行时间减少了20毫秒到370毫秒左右。下面是添加索引后更新的查询执行计划。

enter image description here

1 个答案:

答案 0 :(得分:5)

由于您的ParentID条件和WHERE条件,您需要JOIN上的索引。

之后,您可以尝试将所有列添加为"包含的列"在parent_id索引上。这意味着它甚至不必对聚集索引进行搜索。

CREATE INDEX ix_location_parentids
ON Location (ParentID)
INCLUDE (ParentID, ID, Description, Level)