Как я могу решить проблему с производительностью в моей хранимой процедуре? - PullRequest
0 голосов
/ 13 июня 2019

Как я могу получить лучшую производительность с моим SQL-запросом в SP?Он использует много памяти. Если вы посмотрите под панелью выполнения, вы увидите, что:

IF NOT EXISTS(SELECT * FROM Common.[CustomerxxxIds] WHERE xyzType = @xyzType AND CustomerId = @CustomerId)[/code]

имеет много использования памяти.Как я могу уменьшить это?

ALTER PROCEDURE [Common].[SaveCustomerxxxIds] 
(
    @xyzType    NVARCHAR(128),
    @CustomerId INT,
    @xxxId  INT OUTPUT
)
AS
BEGIN
    SET NOCOUNT ON;

    IF NOT EXISTS(SELECT * FROM Common.[CustomerxxxIds] WHERE xxxType = @xxxType AND CustomerId = @CustomerId)
    BEGIN
        INSERT INTO Common.[CustomerxxxIds]
                    ([xxxId]
                    ,[CustomerId]
                    ,[xxxType])
                VALUES
                    (0
                    ,@CustomerId
                    ,@xxxType)
    END

    UPDATE  Common.[CustomerxxxIds]
    SET     [xxxId] = ([xxxId]) + 1
    WHERE   [xxxType] = @xxxType
            AND CustomerId = @CustomerId

    SELECT  @xxxId = xxxId
    FROM    Common.[CustomerxxxIds]
    WHERE   [xxxType] = @xxxType
            AND CustomerId = @CustomerId
END

Ответы [ 3 ]

2 голосов
/ 13 июня 2019

Вы можете сделать что-то, чтобы избежать «перечитывания» таблицы для получения выходного значения.

После ВСТАВКИ (INSERT INTO Common. [CustomerxxxIds])

Используйте SCOPE_IDxxx (), чтобы получить вновь созданный суррогатный ключ.

Вышеуказанное будет работать только для столбцов IDxxx. Исходя из вашего вопроса, у вас может не быть столбца IDxxx.

См

https://docs.microsoft.com/en-us/sql/t-sql/functions/scope-idxxx-transact-sql?view=sql-server-2017

.........

с помощью UPDATE и / или INSERT вы можете использовать функцию OUTPUT для получения значения.

https://docs.microsoft.com/en-us/sql/t-sql/queries/output-clause-transact-sql?view=sql-server-2017

Это позволяет ИЗБЕГАТЬ последнего оператора выбора («перечитать», как я его называю), чтобы получить желаемое выходное значение.

Очевидно, что полное удаление оператора SELECT улучшит производительность.

..

Ниже приведен простой, но полный пример базы данных Northwind с использованием OUTPUT для INSERT и UPDATE

SELECT 'Before' as Looksie, [ShipperID]
      ,[CompanyName]
      ,[Phone]
  FROM [Northwind].[dbo].[Shippers]

  --
  DECLARE @MyInsertAuditTable table( AuditShipperID INT,  
                           AuditCompanyName nvarchar(40),  
                           AuditPhone nvarchar(24));  
INSERT [Northwind].[dbo].[Shippers] (CompanyName , Phone )
    OUTPUT INSERTED.ShipperID, INSERTED.CompanyName, INSERTED.Phone  
        INTO @MyInsertAuditTable  (AuditShipperID, AuditCompanyName , AuditPhone )

SELECT TOP 1
    --(SELECT MAX(ShipperID) + 1 from dbo.Shippers )
     'Shipper' + LEFT(CONVERT(VARCHAR(38), NEWID()), 12)
    , '(555) 555-5555'
    FROM sys.objects

--Display the result set of the table variable.  
SELECT AuditShipperID, AuditCompanyName, AuditPhone FROM @MyInsertAuditTable;  

  DECLARE @MyUpdateAuditTable table( AuditShipperID INT,  
                           AuditCompanyName nvarchar(40),  
                             AuditOldPhone nvarchar(24),
                           AuditNewPhone nvarchar(24));  

UPDATE [Northwind].[dbo].[Shippers] 

SET Phone = '(777) 555-7777'

OUTPUT inserted.ShipperID,  inserted.CompanyName ,
       deleted.Phone,  
       inserted.Phone
INTO @MyUpdateAuditTable ( AuditShipperID, AuditCompanyName, AuditOldPhone , AuditNewPhone)
FROM [Northwind].[dbo].[Shippers]  shippers
JOIN @MyInsertAuditTable insAudit on shippers.ShipperID = insAudit.AuditShipperID

SELECT * from @MyUpdateAuditTable



SELECT 'After' as Looksie, [ShipperID]
      ,[CompanyName]
      ,[Phone]
  FROM [Northwind].[dbo].[Shippers]

  --

Результаты

Looksie ShipperID   CompanyName Phone
Before  1   Speedy Express  (503) 555-9831
Before  2   United Package  (503) 555-3199
Before  3   Federal Shipping    (503) 555-9931

..

AuditShipperID  AuditCompanyName    AuditPhone
9               Shipper3C062D46-EEA (555) 555-5555

...

AuditShipperID  AuditCompanyName    AuditOldPhone   AuditNewPhone
9               Shipper3C062D46-EEA (555) 555-5555  (777) 555-7777

..

Looksie ShipperID   CompanyName Phone
After   1           Speedy Express  (503) 555-9831
After   2           United Package  (503) 555-3199
After   3           Federal Shipping    (503) 555-9931
After   9           Shipper3C062D46-EEA (777) 555-7777
0 голосов
/ 13 июня 2019

Попробуйте это

    ALTER PROCEDURE [Common].[SaveCustomerxxxIds] 
(
    @xyz NVARCHAR(128),
    @CustomerId INT,
    @xxxId   INT OUTPUT
)
AS
BEGIN
    set @xxxId=null
    --Get xxxId
    SELECT @xxxId=[xxxId] FROM Common.[CustomerxxxIds] WHERE xyz = @xyz AND CustomerId = @CustomerId
    --If @xxxId means no record we should insert 
    if (@xxxId is null)
        begin 
            --When insert we always insert xxxId as 0 then update to one then we collect the  value (one) from db and return it.
            --Better set value directly as one insert it to DB and return it as one. Instead of insert, update, select
            --just insert
            set @xxxId = 1
           INSERT INTO Common.[CustomerxxxIds]
                            ([xxxId]
                            ,[CustomerId]
                            ,[xyz])
                        VALUES
                            (@xxxId
                            ,@CustomerId
                            ,@xyz)
        end 
    else
        begin
            --If we have the value we add one to it update the record and return it.
            --better than update table then select. 
            --We already have the value we add one to it then update table and return the value we have 
            set @xxxId+=1
            UPDATE  Common.[CustomerxxxIds]   SET     [xxxId] = @xxxId
            WHERE   [xyz] = @xyz       AND CustomerId = @CustomerId
        END
end
0 голосов
/ 13 июня 2019

Этого можно добиться, изменив SELECT * на SELECT 1.это может помочь

IF NOT EXISTS (SELECT 1 FROM Common.[CustomerxxxIds] 
               WHERE xyzType = @xyzType AND CustomerId = @CustomerId)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...