1

Я создал таблицу для проверки количества считываемых логических блоков и плана выполнения, выбранного оптимизатором запросов, сравнивая запросы, когда эта таблица имеет индекс, а когда нет.Почему иногда сканирование таблицы происходит быстрее, чем сканирование индекса?

тест стол

create table scan 
( 
     id int identity(1, 1), 
     a varchar(10), 
     b varchar(10), 
     c varchar(10), 
     d varchar(10), 
     e varchar(10), 
     f varchar(10) 
) 

Когда я бегу из этих запросов:

select * from scan 
select id from scan 

я получил 88 и 58 логических операций чтения и алгоритм сканирования таблицы

Тогда я изменить таблица, в которой установлено ограничение pk и его кластерный идентификатор

alter table scan 
add constraint fk_id primary key (id) 

затем запустить те же запросы:

select * from scan 
select id from scan 

, и я получил 90 и 60 сканирования читает и алгоритм сканирования индекса

Возникает вопрос: если оптимизатор запросов выбрать лучший способ для запуска запроса , почему он выбирает сканирование индекса, если сканирование таблицы может читать меньше блока?

+2

Вы просто читаете все строки - индекс ничего не делает. Добавьте предложение WHERE и посмотрите, что произойдет. – dbugger

+1

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

+1

Являются ли ваши номера * актуальными * читаемыми или * оцененными * считаются? На такой небольшой таблице индекс вряд ли будет особенно полезен. –

ответ

3

Когда вы создали ограничение первичного ключа, оно было снесено кластером по умолчанию. Это означает, что куча, которую вы ранее предварительно заказали по этому ключу (id, в вашем случае).

Данные в таблицах могут храниться одним из двух способов: кучи или кластерные индексы. Когда последний создается, первый исчез. Таким образом, SQL Server не может выполнять сканирование таблицы по индексу - это может быть только сканирование индекса (кластерное сканирование индекса, btw - это важно).

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

+0

Но я до сих пор не знаю, почему он читает больше блока с индексом, чем читает при сканировании таблицы. Без индекса у меня есть 7 столбцов, представьте, что каждый из них имеет 1kb, а блок - 14kb, поэтому он читает 2 строки на блок. С индексом у нас есть 2 столбца, один для индекса и другой для указателя на строковый адрес. Если у вас есть и 1kb каждый, блок знает, что будет 7 строк. Поэтому я читаю больше информации с меньшим количеством блоков. Я думаю, что он должен читать либо меньше блоков, чем сканирование таблицы, либо гораздо больше блоков, чем сканирование таблицы в случае SELECT *, потому что он будет читать «таблицу индексов» и реальную таблицу. – Mucida

+1

@Mucida, куча физически реализована как двойной связанный список, где каждая таблица имеет 2 указателя - на предыдущем и на следующих страницах в куче. Кластеризованный индекс реализуется как B-дерево, поэтому он потребляет немного больше места для страниц с корневым и промежуточным уровнями (в среднем около 1% от размера таблицы). В зависимости от того, является ли ваша таблица кучей или нет, будет использоваться сканирование таблицы (то есть сканирование кучи) или сканирование с кластеризованным индексом.И вы не можете иметь обе структуры на диске для одной и той же таблицы одновременно - это всего лишь одна таблица. –

+0

спасибо, у меня есть идея о пространстве. Но почему, если я выполняю этот запрос «SELECT id, FROM Scan WHERE id BETWEEN 100 AND 9999», он все еще использует сканирование таблицы? Почему он не идет в таблицу с отсортированным идентификатором и адресом строки, глядя только на блок с соответствующим поиском, а затем переходя к адресам, чтобы искать значения «a»? В этом случае индекс в id бесполезен. Если я создаю индекс с «id» AND «a», тогда он работает быстрее, делая поиск индекса. – Mucida

Смежные вопросы