Неожиданная статистика запросов при выполнении нескольких последовательных операторов - PullRequest
0 голосов
/ 03 мая 2019

Использование SQL Server 2016 и более поздних версий

В настоящее время я оцениваю два метода отображения результатов поиска. Показать все "продукты", которые соответствуют "критериям".

Я искал преимущества сохранения списка идентификаторов, которые соответствуют критериям в временной таблице, и затем присоединения к моим основным продуктам по сравнению с динамически создаваемым сеансным представлением, в котором идентификаторы закодированы в качестве значений.

Пример скриптов ниже. Я опустил сам стол основного продукта, так как он представляет собой большой плоский стол, но содержит фирменные детали компании. Сам код не проблема, а статистика, которую он генерирует.

SET STATISTICS IO, TIME OFF;

DROP TABLE IF EXISTS dba.Temp;
DROP VIEW IF EXISTS dba.Test1;
DROP VIEW IF EXISTS dba.Test2;

CREATE TABLE dba.Temp (ProductID INT);

INSERT INTO dba.Temp (ProductID)
SELECT  TOP 1000
        ProductID
  FROM  dbo.Products
 ORDER BY NEWID();
GO

CREATE VIEW dba.Test1
AS
    SELECT  P.*
      FROM  Products P
      JOIN  dba.Temp T ON T.ProductID = P.ProductID;
GO

DECLARE @strSQL AS NVARCHAR(MAX);

SET @strSQL = N'';

SELECT  @strSQL = @strSQL + N',(' + CAST(ProductID AS NVARCHAR(MAX)) + N')'
  FROM  dba.Temp;

SET @strSQL = STUFF(@strSQL, 1, 1, ('CREATE VIEW dba.Test2 AS SELECT P.* FROM Products P JOIN (VALUES ')) + N') T (ProductID) ON T.ProductID = P.ProductID';

EXEC sp_executesql @stmt = @strSQL;
GO

SET STATISTICS IO, TIME ON;

PRINT '------------------------------ Test 1'; 
SELECT * FROM dba.Test1; 
PRINT '------------------------------ Test 2'; 
SELECT * FROM dba.Test2; 
PRINT '------------------------------ End';

SET STATISTICS IO, TIME OFF;

Я обнаружил, что между двумя вариантами в моих наборах данных было очень мало различий, но я получал очень странные результаты в зависимости от того, как я тестировал.

Если я читаю только из теста 1, я получаю статистику, аналогичную приведенной ниже, с небольшими колебаниями прошедшего времени - я не единственный пользователь на сервере.

SQL Server parse and compile time: 
   CPU time = 8 ms, elapsed time = 8 ms.
------------------------------ Test 1

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.

(1000 rows affected)
Table 'Products'. Scan count 0, logical reads 3071, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Temp'. Scan count 1, logical reads 2, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

 SQL Server Execution Times:
   CPU time = 47 ms,  elapsed time = 56 ms.

Выполняя тест 2, я получил очень похожие результаты только с более низким IO (ожидалось, так как временная таблица не читалась из)

SQL Server parse and compile time: 
   CPU time = 46 ms, elapsed time = 46 ms.
------------------------------ Test 2

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.

(1000 rows affected)
Table 'Products'. Scan count 0, logical reads 3071, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

 SQL Server Execution Times:
   CPU time = 47 ms,  elapsed time = 57 ms.

Однако, выполняя два теста вместе, я вижу значительно более медленные результаты, при которых любой запрос выполняется вторым.

SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 0 ms.
------------------------------ Test 1

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.

(1000 rows affected)
Table 'Products'. Scan count 0, logical reads 3063, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Temp'. Scan count 1, logical reads 2, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

 SQL Server Execution Times:
   CPU time = 47 ms,  elapsed time = 56 ms.
------------------------------ Test 2

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.

(1000 rows affected)
Table 'Products'. Scan count 0, logical reads 3063, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

 SQL Server Execution Times:
   CPU time = 62 ms,  elapsed time = 200 ms.
------------------------------ End

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.

Есть ли логическая причина для искаженных результатов для второго запроса? Это то, что первый запрос создает нагрузку, которая влияет на второй запрос? Мне интересно, что я что-то упустил или у меня есть фундаментальное недоразумение. Так я обычно настраиваю свои процессы, акцентируясь на IO, следя за временем. Если мне нужно будет скорректировать свою методологию настройки, то мы с благодарностью примем любой совет.

...