Sql server SQL Server存储过程执行时间较长

Sql server SQL Server存储过程执行时间较长,sql-server,stored-procedures,Sql Server,Stored Procedures,我还是SQL新手。我制作了一个内部有一些循环的存储过程。我想在Delphi中创建一个参数很少的存储过程 SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO ALTER PROCEDURE [dbo].[sp_operator6] @awal DATETIME, @akhir DATETIME, @pumpsMotor VARCHAR(500), @pumpsMobil VARCHAR(500), @pumps

我还是SQL新手。我制作了一个内部有一些循环的存储过程。我想在Delphi中创建一个参数很少的存储过程

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE [dbo].[sp_operator6]
    @awal DATETIME,
    @akhir DATETIME,
    @pumpsMotor VARCHAR(500),
    @pumpsMobil VARCHAR(500),
    @pumpsSolar VARCHAR(500)
AS
BEGIN    
    DECLARE @tbl_pumpMotor TABLE (pumpnumber INT)

    INSERT INTO @tbl_pumpMotor 
        SELECT * 
        FROM dbo.SplitList(@pumpsMotor,',')

    DECLARE @tbl_pumpMobil TABLE (pumpnumber INT)

    INSERT INTO @tbl_pumpMobil 
        SELECT * 
        FROM dbo.SplitList(@pumpsMobil,',')

    DECLARE @tbl_pumpSolar TABLE (pumpnumber INT)

    INSERT INTO @tbl_pumpSolar 
        SELECT * 
        FROM dbo.SplitList(@pumpsSolar,',')

    DECLARE @var2 VARCHAR(50)
    DECLARE @tbl_result TABLE (Nama VARCHAR(MAX),
                               [shift 1 Motor] INT, 
                               [shift 2 Motor] INT, 
                               [shift 3 Motor] INT,
                               [shift 1 Mobil] INT, 
                               [shift 2 Mobil] INT, 
                               [shift 3 Mobil] INT,
                               [shift 1 Solar] INT, 
                               [shift 2 Solar] INT, 
                               [shift 3 Solar] INT)

    DECLARE @tbl_shift1 TABLE (shiftid INT)

    INSERT INTO @tbl_shift1 
        SELECT [id] 
        FROM [shift] 
        WHERE bizdate BETWEEN @awal AND @akhir 
          AND shiftworkdayid = 1

   declare @tbl_shift2 table (shiftid int)
insert into @tbl_shift2 select [id] from [shift] where bizdate between @awal and @akhir and shiftworkdayid=2

declare @tbl_shift3 table (shiftid int)
insert into @tbl_shift3 select [id] from [shift] where bizdate between @awal and @akhir and shiftworkdayid=3

declare hk_cursor cursor for
select distinct  operatorname from [transaction] where [date] between @awal and @akhir and OperatorName<>'RFID'

OPEN hk_cursor
fetch next from hk_cursor into @var2

while (@@fetch_status=0)
BEGIN
insert into @tbl_result
select operator.nama, 
shift1Motor.[shift 1 Motor], shift2Motor.[shift 2 Motor], shift3Motor.[shift 3 Motor],
shift1Mobil.[shift 1 Mobil], shift2Mobil.[shift 2 MoBIL], shift3Mobil.[shift 3 MoBIL],
shift1SOLAR.[shift 1 SOLAR], shift2SOLAR.[shift 2 SOLAR], shift3SOLAR.[shift 3 SOLAR]
from

  (select top 1 operatorname as Nama from [Transaction] where operatorname=@var2) as operator,
-- ====================================== MOTOR
  (SELECT count (distinct [ShiftId]) as [shift 1 Motor]  
  FROM [Transaction] 
  where 
  [date] between @awal and @akhir
  and operatorname = @var2
  and pumpnumber in ( select pumpnumber from @tbl_pumpMotor)
  and shiftid in (select shiftid from @tbl_shift1)
  )
  as shift1Motor,

(SELECT count (distinct 
      [ShiftId])
      as [shift 2 Motor]

  FROM [Transaction]
  where 
  [date] between @awal and @akhir
  and operatorname = @var2
  and pumpnumber in ( select pumpnumber from @tbl_pumpMotor)
  and shiftid in (select shiftid from @tbl_shift2)
 ) 
  as shift2Motor,

  (SELECT count (distinct [ShiftId])as [shift 3 Motor]
  FROM [Transaction]
  where 
  [date] between @awal and @akhir
  and operatorname = @var2
  and pumpnumber in ( select pumpnumber from @tbl_pumpMotor)
  and shiftid in (select shiftid from @tbl_shift3)
 ) 
  as shift3Motor,

-- ====================================== MOBIL

(SELECT count (distinct [ShiftId]) as [shift 1 MoBIL]
FROM [Transaction] 
  where 
  [date] between @awal and @akhir
  and operatorname = @var2
  and pumpnumber in ( select pumpnumber from @tbl_pumpMobil)
  and shiftid in (select shiftid from @tbl_shift1)
  )
as shift1Mobil,

(SELECT count (distinct [ShiftId])as [shift 2 MoBIL] 
FROM [Transaction]
  where 
  [date] between @awal and @akhir
  and operatorname =@var2
 and pumpnumber in ( select pumpnumber from @tbl_pumpMobil)
  and shiftid in (select shiftid from @tbl_shift2)
 ) 
  as shift2Mobil,

  (SELECT count (distinct [ShiftId])as [shift 3 MoBIL]
  FROM [Transaction] 
  where 
  [date] between @awal and @akhir
  and operatorname = @var2
  and pumpnumber in ( select pumpnumber from @tbl_pumpMobil)
  and shiftid in (select shiftid from @tbl_shift3)
 ) 
  as shift3Mobil,

  -- ====================================== SOLAR

  (SELECT count (distinct [ShiftId]) as [shift 1 SOLAR]   
 FROM [Transaction]
  where 
  [date] between @awal and @akhir
  and operatorname = @var2
  and pumpnumber in ( select pumpnumber from @tbl_pumpSolar)
  and shiftid in (select shiftid from @tbl_shift1)
  )
as shift1SOLAR,

(SELECT count (distinct [ShiftId]) as [shift 2 SOLAR]
  FROM [Transaction] 
  where 
  [date] between @awal and @akhir
  and operatorname = @var2
  and pumpnumber in ( select pumpnumber from @tbl_pumpSolar)
  and shiftid in (select shiftid from @tbl_shift2)
 ) 
  as shift2SOLAR,

  (SELECT count (distinct [ShiftId]) as [shift 3 SOLAR]
  FROM [Transaction] 
  where 
  [date] between @awal and @akhir
  and operatorname = @var2
  and pumpnumber in ( select pumpnumber from @tbl_pumpSolar)
  and shiftid in (select shiftid from @tbl_shift3)
 ) 
  as shift3SOLAR
FETCH NEXT from hk_cursor into @var2
END

close hk_cursor
deallocate hk_cursor

select * from @tbl_result
end
在本地服务器上执行结果25条记录花费了7分钟。 有没有比这种方法更简单的方法来编写这个存储过程? 非常感谢您的帮助


提前感谢

首先,你需要从集合的角度来思考,避免循环,尤其是不必要的循环

接下来是一个巨大的交叉连接,这通常不利于性能

如果在这些表变量中有多于几条记录,则丢弃它们,改用临时表,然后对它们进行索引

考虑向表变量(或临时表)添加一个类型列,并将所有信息放在一个表中。这可能会使使用case语句进行聚合变得更简单。透视查询也可能有用


您还需要查看执行计划,可能缺少一些有用的索引

旁注:存储过程不应使用
sp
前缀。微软已经这样做了,而且你确实有可能在将来的某个时候发生名称冲突。最好只是简单地避免使用
sp.
并使用其他东西作为前缀,或者根本不使用前缀!谢谢,这样可以避免这种情况。让我们从您的拆分器开始。它看起来像什么?它有环吗?您的过程代码非常有问题。它看起来像一个dotnet应用程序,而不是数据检索。尽可能避免使用循环和游标。然后,您的主查询是一堆单独的select语句。整个过程需要彻底检修。它可以简化为一个insert语句,没有循环和几十个查询。我甚至建议您的分隔列表可以成为表值参数并避免拆分。寻求性能帮助的问题应包括所涉及表的DDL、DML以及测试数据。如果您的测试数据很大,请尝试为表编写架构和统计信息脚本(
右键单击数据库->生成脚本->选择特定数据库对象->在下一个屏幕中选择高级并选择脚本统计信息)
并将其粘贴到问题中..使用此信息,任何人都可以复制您面临的同一问题。否则,回答您的问题将变得非常困难。粘贴服务器版本还有其他帮助…当您希望插入多行时,请避免使用表变量。请改用临时表。区别在于SQL server为临时表而不是表变量构建静态(它只是假设一行)…这种差异可能会对结果执行计划产生非常实际的影响。感谢HLGEM,正如您所说,我避免了循环,所以我在程序内部进行循环。它使查询更快。
execute sp_operator6 '2015-8-10','2015-8-15','4,3,33,34,35,36','5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22','23,24,27,28,31,32'