SQL Server 2005: - Статистика ввода-вывода для IF EXISTS и COUNT (*)> 0 Одинаковы? - PullRequest
2 голосов
/ 29 октября 2010

РЕДАКТИРОВАТЬ : -

При использовании PK в столбце Id производится следующее для EXISTS и COUNT (*)> 0

Table 'TableWithHugeData'. Scan count 0, logical reads 3, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

IF OBJECT_ID('TableWithHugeData') IS NOT NULL
BEGIN
DROP TABLE TableWithHugeData
END

CREATE TABLE TableWithHugeData
(
ID UNIQUEIDENTIFIER,
Name varchar(max)
)


DECLARE @Counter INT
SELECT @Counter = 0
WHILE (@Counter < 50000)
BEGIN
INSERT INTO TableWithHugeData
VALUES (NewId(),'Ashish ' + Convert(varchar(5000),@Counter))
SELECT @Counter = @Counter +1
END

EXISTS

DBCC FreeProcCache
DBCC DROPCLEANBUFFERS
SET  STATISTICS IO ON
DECLARE @Id UNIQUEIDENTIFIER
SELECT @Id = '28BD1F4C-7D89-4731-9D2C-21ECB20500F8'
IF EXISTS (SELECT * FROM TableWithHugeData WHERE Id = @Id)
BEGIN
SELECT CONVERT(BIT, 1)
END
ELSE
BEGIN
SELECT CONVERT(BIT, 0)
END

Статистика ввода-вывода для EXISTS: -

Таблица «TableWithHugeData».Сканирование 1, логическое чтение 6, физическое чтение 1, чтение с опережением 270, логическое чтение с лота 0, физическое чтение с лоба 0, чтение с опережением чтения 0.

COUNT (*)> 0

DBCC FreeProcCache
DBCC DROPCLEANBUFFERS
DECLARE @Id UNIQUEIDENTIFIER
SELECT @Id = '28BD1F4C-7D89-4731-9D2C-21ECB20500F8'
IF (SELECT COUNT(*) FROM TableWithHugeData WHERE Id = @Id)>0
BEGIN
SELECT CONVERT(BIT, 1)
END
ELSE
BEGIN
SELECT CONVERT(BIT, 0)
END

* Статистика ввода-вывода для счета ()> 0 **: -

Таблица 'TableWithHugeData'.Сканирование 1, логическое чтение 6, физическое чтение 1, чтение с опережением 270, логическое чтение с лоба 0, физическое чтение с лоба 0, чтение с опережением чтения 0.

Как видите, статистика ввода-вывода для EXISTSи COUNT (*)> 0 одинаковы.Я думал, что EXISTS будет быстрее и будет выполнять меньше операций чтения.Я что-то здесь упускаю?Будет ли определение первичного ключа иметь какое-либо значение?

1 Ответ

3 голосов
/ 29 октября 2010

Как видите, статистика ввода-вывода для EXISTS и COUNT (*)> 0 одинакова. Я думал, что EXISTS будет быстрее и будет выполнять меньше операций чтения. Я что-то здесь упускаю?

SQL Server читает данные по блокам.

Если искомая запись находится в последнем блоке (или не найдена вообще), тогда EXISTS все равно придется сканировать все блоки.

Будет ли определение первичного ключа иметь какое-либо значение?

Да.

С PRIMARY KEY, EXISTS и COUNT(*) всегда будут одинаковыми (поиск по одному индексу).

Без него EXISTS остановится в первом матче, а COUNT(*) продолжится до конца таблицы.

Обновление:

Извините, раньше я ошибался.

Кажется, что SQL Server оптимизирует COUNT(*) > 0 до EXISTS, так что да, статистика будет такой же.

DBCC FreeProcCache
CHECKPOINT
DBCC DROPCLEANBUFFERS
SET  STATISTICS IO ON
DECLARE @id UNIQUEIDENTIFIER
SET @id = '7C65EBB1-1242-4084-8BB4-3CC92CA2BE51'
IF      (
        SELECT  COUNT(*)
        FROM    tablewithhugedata
        WHERE   id = @id
        ) > 0
BEGIN
        SELECT CONVERT(BIT, 1)
END
ELSE
BEGIN
        SELECT CONVERT(BIT, 0)
END

DBCC execution completed. If DBCC printed error messages, contact your system administrator.
DBCC execution completed. If DBCC printed error messages, contact your system administrator.
Table 'TableWithHugeData'. Scan count 1, logical reads 1, physical reads 0, read-ahead reads 270, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

(1 row(s) affected)

И немного другой запрос:

DBCC FreeProcCache
CHECKPOINT
DBCC DROPCLEANBUFFERS
SET  STATISTICS IO ON
DECLARE @id UNIQUEIDENTIFIER
SET @id = '7C65EBB1-1242-4084-8BB4-3CC92CA2BE51'
IF EXISTS
        (
        SELECT  1
        FROM    tablewithhugedata
        WHERE   id = @id
        )
BEGIN
        SELECT CONVERT(BIT, 1)
END
ELSE
BEGIN
        SELECT CONVERT(BIT, 0)
END

DBCC FreeProcCache
CHECKPOINT
DBCC DROPCLEANBUFFERS
SET  STATISTICS IO ON
DECLARE @id UNIQUEIDENTIFIER
SET @id = '7C65EBB1-1242-4084-8BB4-3CC92CA2BE51'
IF      (
        SELECT  COUNT(*)
        FROM    tablewithhugedata
        WHERE   id = @id
        ) BETWEEN 1 AND 2
BEGIN
        SELECT CONVERT(BIT, 1)
END
ELSE
BEGIN
        SELECT CONVERT(BIT, 0)
END

DBCC execution completed. If DBCC printed error messages, contact your system administrator.
DBCC execution completed. If DBCC printed error messages, contact your system administrator.
Table 'TableWithHugeData'. Scan count 2, logical reads 266, physical reads 6, read-ahead reads 270, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

(1 row(s) affected)

Второй запрос должен знать точное значение COUNT(*), поэтому он читает все блоки (266 логическое чтение против 1 для EXISTS / COUNT(*) > 0).

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