Оценка мощности SARG, почему не полносканирование?

Почему нет полного сканирования (на SQL 2008 R2 и 2012)?

Данные теста:

DROP TABLE dbo.TestTable
GO  
CREATE TABLE dbo.TestTable
(
   TestTableID INT IDENTITY PRIMARY KEY,
   VeryRandomText VarChar(50),
   VeryRandomText2 VarChar(50)
)
Go
Set NoCount ON
Declare @i int
Set @i = 0
While @i < 10000
Begin
   Insert Into dbo.TestTable(VeryRandomText, VeryRandomText2)
      Values(Cast(Rand()*10000000 as VarChar(50)), Cast(Rand()*10000000 as VarChar(50)));
   Set @i = @i + 1;
End
Go
CREATE Index IX_VeryRandomText On dbo.TestTable
(
    VeryRandomText
)
Go

При выполнении запроса:

Select * From dbo.TestTable Where VeryRandomText = N'111' -- bad

Получить предупреждение (как и ожидалось, поскольку сравнение данных nchar с столбцом varchar):

<PlanAffectingConvert ConvertIssue="Cardinality Estimate" Expression="CONVERT_IMPLICIT(nvarchar(50),[DemoDatabase].[dbo].[TestTable].[VeryRandomText],0)" />

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

введите описание изображения здесь>> </p>

<p> Конечно, это хорошо, потому что в этом конкретном случае выполнение выполняется быстрее, чем если бы было полное сканирование. </p>

<p> <strong> Но я не могу понять, как SQL Server пришел к решению сделать этот план. </strong> </p>

<p> Кроме того, если сопоставление сервера будет сопоставлением Windows на уровне сервера и уровнем базы данных сортировки SQL Server, это приведет к полному сканированию по одному и тому же запросу. </p></body></html>

11 голосов | спросил Jānis 3 J000000Friday15 2015, 11:30:40

2 ответа


8

При сравнении значений разных типов данных SQL Server следуйте Приоритет типа данных правила. Поскольку nvarchar имеет более высокий приоритет, чем varchar, SQL Server должен преобразовать данные столбца в nvarchar перед сравнением значений. Это означает применение функции в столбце, и это сделает запрос неприемлемым.

SQL Server делает все возможное, чтобы защитить вас от ваших ошибок, поэтому он использует технику, описанную Пол Уайт в блоге Сравнение сопоставлений SQL с сопоставлениями Windows

В принципе, сортировка Windows использует тот же алгоритм для varchar и nvarchar, где сортировка SQL использует другой алгоритм для данных varchar и тот же алгоритм, что и сортировка Windows для данных nvarchar.

Таким образом, переход от varchar к nvarchar при сортировке Windows будет использовать тот же алгоритм, и SQL Server может создавать ряд значений, в вашем случае, литерал nvarchar для получения строк из индекса столбца сортировки SQL varchar. Однако, когда сортировка столбца varchar представляет собой SQL-сортировку, которая невозможна из-за использования используемого алгоритма.


Update:

Демонстрация различных порядков сортировки для столбцов varchar с использованием окон и сопоставления sql.

скрипт SQL

Настройка схемы MS SQL Server 2014 :

create table T(C varchar(10));

insert into T values('a-b'),('aa'),('ac');

Запрос 1 :

select C
from T
order by C collate SQL_Latin1_General_CP1_CI_AS;

Результаты :

|   C |
|-----|
| a-b |
|  aa |
|  ac |

Запрос 2 :

select C
from T
order by C collate Latin1_General_100_CI_AS;

Результаты :

|   C |
|-----|
|  aa |
| a-b |
|  ac |
ответил Mikael Eriksson 3 J000000Friday15 2015, 19:59:49
0

Вы должны помнить, что листовые узлы некластеризованного индекса состоят из страниц индексов, содержащих Кластерный ключ или RID, чтобы найти строку данных.

В вашем предложении where вы указываете VeryRandomText = N'111' Так как на VeryRandomText существует Non-кластерный индекс (create index создаст некластеризованный индекс, если вы не явным образом расскажу, чтобы создать кластерный), самый дешевый способ найти данные - это сканировать индекс, чтобы найти rowid, а затем извлечь данные для строки.

Если вы создадите кластерный индекс

CREATE clustered Index IX_VeryRandomText On dbo.TestTable (VeryRandomText)

или первичный ключ на VeryRandomText, вы получите сканирование этого индекса.

Смотрите книги онлайн или здесь: http://www.sqlforge.com/w/Clustered_index, _nonclustered_index, _or_heap

ответил Spörri 3 J000000Friday15 2015, 14:48:41

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132