为什么SQL查询执行时间太长?

时间:2018-09-01 07:17:08

标签: sql sql-server tsql

当我执行此操作时,起初速度不错,但现在要花很长时间,速度很慢。我不知道为什么,但是我想也许我应该清除缓存。 我想说大约需要1天,但还没有完成20%。 实际上,它大约在数据库SELECT中的TABLE上的[spt]和另一个数据库INSERT中的[AB_Warehouse]上,但是它们都在一个服务器上。

注意:在数据库[spt]中提交了一个,我们有这样的数据 “ aa + tt + bb + rr + yy”,我使用函数StringSplitXML进行了拆分,并且每个函数都插入了[Workspaces_Tbl] Level1 ... 15

这是我的查询:

USE [spt]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

BEGIN    
    DECLARE @ID decimal(20, 0);
    DECLARE @parent_id decimal(20, 0);
    DECLARE @Type int;
    DECLARE @workspacetype_id decimal(10, 0);
    DECLARE @isvirtual decimal(1, 0);
    DECLARE @enable decimal(1, 0);
    DECLARE @Level1 nvarchar(MAX);
    DECLARE @Level2 nvarchar(MAX);
    DECLARE @Level3 nvarchar(MAX);
    DECLARE @Level4 nvarchar(MAX);
    DECLARE @Level5 nvarchar(MAX);
    DECLARE @Level6 nvarchar(MAX);
    DECLARE @Level7 nvarchar(MAX);
    DECLARE @Level8 nvarchar(MAX);
    DECLARE @Level9 nvarchar(MAX);
    DECLARE @Level10 nvarchar(MAX);
    DECLARE @Level11 nvarchar(MAX);
    DECLARE @Level12 nvarchar(MAX);
    DECLARE @Level13 nvarchar(MAX);
    DECLARE @Level14 nvarchar(MAX);
    DECLARE @Level15 nvarchar(MAX);
    DECLARE @titles_tmp nvarchar(MAX);

    DECLARE @cont_spilit_tittle int;
    DECLARE @parent_titles_tmp nvarchar(MAX);
    DECLARE @cont_tmp int;
    DECLARE @cont int;
    SELECT @cont = COUNT(*) FROM septa.dbo.workspaces;
    SET @cont_tmp = 0;

    While(@cont_tmp<@cont)
    BEGIN  
        SET @ID = (SELECT spt.dbo.workspaces.workspace_id FROM septa.dbo.workspaces ORDER BY workspace_id ASC OFFSET @cont_tmp ROWS FETCH NEXT 1 ROWS ONLY)
        SET @parent_id = (SELECT septa.dbo.workspaces.parent_id FROM septa.dbo.workspaces ORDER BY workspace_id ASC OFFSET @cont_tmp ROWS FETCH NEXT 1 ROWS ONLY)
        SET @workspacetype_id = (SELECT septa.dbo.workspaces.workspacetype_id FROM septa.dbo.workspaces ORDER BY workspace_id ASC OFFSET @cont_tmp ROWS FETCH NEXT 1 ROWS ONLY)
        SET @isvirtual = (SELECT septa.dbo.workspaces.isvirtual FROM septa.dbo.workspaces ORDER BY workspace_id ASC OFFSET @cont_tmp ROWS FETCH NEXT 1 ROWS ONLY)
        SET @enable = (SELECT septa.dbo.workspaces.enable FROM septa.dbo.workspaces ORDER BY workspace_id ASC OFFSET @cont_tmp ROWS FETCH NEXT 1 ROWS ONLY)
        SET @titles_tmp = (SELECT septa.dbo.workspaces.title FROM septa.dbo.workspaces ORDER BY workspace_id ASC OFFSET @cont_tmp ROWS FETCH NEXT 1 ROWS ONLY)
        SET @parent_titles_tmp = (SELECT septa.dbo.workspaces.parent_titles FROM septa.dbo.workspaces ORDER BY workspace_id ASC OFFSET @cont_tmp ROWS FETCH NEXT 1 ROWS ONLY)

        IF OBJECT_ID('tempdb..#MyTempTable') IS NOT NULL DROP TABLE #MyTempTable
        SELECT IDENTITY(int, 1, 1) AS 'RowID',* into #MyTempTable 
        FROM StringSplitXML(@parent_titles_tmp,'+')

        insert into #MyTempTable VALUES (@titles_tmp)

        SET @cont_spilit_tittle = (SELECT COUNT(*) FROM #MyTempTable)

        IF(@cont_spilit_tittle<0)SET @cont_spilit_tittle = 1

        SET @Type = @cont_spilit_tittle

        WHILE(@cont_spilit_tittle < 15)
        BEGIN
            insert into #MyTempTable VALUES ('')
            SET @cont_spilit_tittle = CAST(@cont_spilit_tittle AS INT) + 1
        END

        SET @Level1 = (SELECT Value FROM #MyTempTable ORDER BY RowID ASC OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY)
        SET @Level2 = (SELECT Value FROM #MyTempTable ORDER BY RowID ASC OFFSET 1 ROWS FETCH NEXT 1 ROWS ONLY)
        SET @Level3 = (SELECT Value FROM #MyTempTable ORDER BY RowID ASC OFFSET 2 ROWS FETCH NEXT 1 ROWS ONLY)
        SET @Level4 = (SELECT Value FROM #MyTempTable ORDER BY RowID ASC OFFSET 3 ROWS FETCH NEXT 1 ROWS ONLY)
        SET @Level5 = (SELECT Value FROM #MyTempTable ORDER BY RowID ASC OFFSET 4 ROWS FETCH NEXT 1 ROWS ONLY)
        SET @Level6 = (SELECT Value FROM #MyTempTable ORDER BY RowID ASC OFFSET 5 ROWS FETCH NEXT 1 ROWS ONLY)
        SET @Level7 = (SELECT Value FROM #MyTempTable ORDER BY RowID ASC OFFSET 6 ROWS FETCH NEXT 1 ROWS ONLY)
        SET @Level8 = (SELECT Value FROM #MyTempTable ORDER BY RowID ASC OFFSET 7 ROWS FETCH NEXT 1 ROWS ONLY)
        SET @Level9 = (SELECT Value FROM #MyTempTable ORDER BY RowID ASC OFFSET 8 ROWS FETCH NEXT 1 ROWS ONLY)
        SET @Level10 = (SELECT Value FROM #MyTempTable ORDER BY RowID ASC OFFSET 9 ROWS FETCH NEXT 1 ROWS ONLY)
        SET @Level11 = (SELECT Value FROM #MyTempTable ORDER BY RowID ASC OFFSET 10 ROWS FETCH NEXT 1 ROWS ONLY)
        SET @Level12 = (SELECT Value FROM #MyTempTable ORDER BY RowID ASC OFFSET 11 ROWS FETCH NEXT 1 ROWS ONLY)
        SET @Level13 = (SELECT Value FROM #MyTempTable ORDER BY RowID ASC OFFSET 12 ROWS FETCH NEXT 1 ROWS ONLY)
        SET @Level14 = (SELECT Value FROM #MyTempTable ORDER BY RowID ASC OFFSET 13 ROWS FETCH NEXT 1 ROWS ONLY)
        SET @Level15 = (SELECT Value FROM #MyTempTable ORDER BY RowID ASC OFFSET 14 ROWS FETCH NEXT 1 ROWS ONLY)


        INSERT INTO [AB_Warehouse].[dbo].[Workspaces_Tbl]
           ([ID]
           ,[parent_id]
           ,[Type]
           ,[workspacetype_id]
           ,[isvirtual]
           ,[enable]
           ,[Level1]
           ,[Level2]
           ,[Level3]
           ,[Level4]
           ,[Level5]
           ,[Level6]
           ,[Level7]
           ,[Level8]
           ,[Level9]
           ,[Level10]
           ,[Level11]
           ,[Level12]
           ,[Level13]
           ,[Level14]
           ,[Level15])
     VALUES
            (
            @ID,
            @parent_id,
            @Type,
            @workspacetype_id,
            @isvirtual,
            @enable,
            @Level1,
            @Level2,
            @Level3,
            @Level4,
            @Level5,
            @Level6,
            @Level7,
            @Level8,
            @Level9,
            @Level10,
            @Level11,
            @Level12,
            @Level13,
            @Level14,
            @Level15
            ) 

        SET @cont_tmp = CAST(@cont_tmp AS INT) + 1
    END  


 RETURN
END

1 个答案:

答案 0 :(得分:4)

作为思考如何解决此问题的方法的提示。

select t.id, t.title, l.*
from test t
cross apply (
  select 
    p.cnt [Level-Count], 
    ISNULL(p.[Level-1], '') [Level-1], 
    ISNULL(p.[Level-2], '') [Level-2],
    ISNULL(p.[Level-3], '') [Level-3],
    ISNULL(p.[Level-4], '') [Level-4]
  from (
    select 
      s.value, 
      'Level-' + cast(row_number() over (order by (select 1)) as varchar(10)) rn,
      count(*) over () - CASE WHEN t.parent_list = '' THEN 1 ELSE 0 END cnt
    from STRING_SPLIT(
      t.parent_list 
      + CASE WHEN t.parent_list = '' THEN '' ELSE '+' END 
      + cast(t.id as varchar(10))
      + CASE WHEN t.parent_list = '' THEN '+' ELSE '' END
      , '+'
    ) s
  ) s
  pivot ( 
    max(s.value) for s.rn in (
      [Level-1], 
      [Level-2], 
      [Level-3], 
      [Level-4]) 
  ) p
) l

类似的东西可以替换您发布的整个脚本。 为了分批处理这些数据,可能仍保留一些循环。但是大部分代码都是不必要的(临时表等)。

| id |        title | Level-Count | Level-1 | Level-2 | Level-3 | Level-4 |
|----|--------------|-------------|---------|---------|---------|---------|
|  1 |       item 1 |           1 |       1 |         |         |         |
|  2 |     item 1/2 |           2 |       1 |       2 |         |         |
|  3 |       item 3 |           1 |       3 |         |         |         |
|  4 |     item 3/4 |           2 |       3 |       4 |         |         |
|  5 |   item 3/4/5 |           3 |       3 |       4 |       5 |         |
|  6 | item 3/4/5/6 |           4 |       3 |       4 |       5 |       6 |
|  7 |     item 2/7 |           3 |       1 |       2 |       7 |         |
|  8 |       item 8 |           1 |       8 |         |         |         |

http://sqlfiddle.com/#!18/7aa71/31