Сканирование таблиц и индексирование в SQL - PullRequest
7 голосов
/ 02 января 2012

В чем разница между сканированием таблиц и индексом в SQL и где оно используется конкретно?

Ответы [ 4 ]

13 голосов
/ 02 января 2012

Сканирование таблицы означает итерацию по всем строкам таблицы.

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

Обычно сканирование индексадешевле, чем сканирование таблицы, потому что индекс более плоский, чем таблица.

Они много библиографируют об этой проблеме.Пример:

Доступ к индексу - это метод доступа, при которомSQL Server использует существующий индекс для чтения и записи страниц данных.Поскольку доступ по индексу значительно уменьшает количество операций чтения ввода-вывода, он часто превосходит сканирование таблицы.

В этом методе строка извлекается путем обхода индекса с использованием значений индексированных столбцов, указанных в операторе.Сканирование индекса извлекает данные из индекса на основе значения одного или нескольких столбцов в индексе.Чтобы выполнить сканирование индекса, Oracle ищет в индексе значения индексированных столбцов, к которым обращается оператор.Если оператор обращается только к столбцам индекса, Oracle считывает значения индексированных столбцов непосредственно из индекса, а не из таблицы.

11 голосов
/ 02 января 2012

Большинство механизмов запросов имеют оптимизатор запросов, который пытается сгенерировать эффективную стратегию выполнения запросов.Если доступны индексы, которые могут сделать запрос быстрее, то оптимизатор запросов выполнит сканирование индекса или поиск индекса, в противном случае сканирование таблицы.

Пример:

SELECT * FROM tbl WHERE category_id = 5;

Если естьнет индекса для category_id, тогда будет выполнено сканирование таблицы, то есть каждая отдельная запись в таблице будет проверена на правильность category_id.

Если, однако, category_id проиндексирован, все усложняется.Если таблица очень большая, вероятно, будет выбран поиск по индексу.Однако, если таблица небольшая, оптимизатор может решить, что сканирование таблицы все еще происходит быстрее, поскольку для доступа к индексу требуются некоторые дополнительные затраты.Если category_id недостаточно избирателен, например, если есть только две категории, сканирование таблицы может быть быстрее даже для больших таблиц.

Индексы обычно организованы в виде древовидных структур.Поиск элемента в дереве - это операция O (log n).Сканирование таблицы - это операция O (n).Скорость в основном определяется количеством обращений к диску, необходимых для выполнения запроса.Сначала поиск индекса, а затем доступ к таблице для найденных записей может привести к большему количеству обращений к диску для небольших таблиц.

Давайте посмотрим на другой запрос:

SELECT category_id FROM tbl WHERE category_id BETWEEN 10 AND 100;

Здесь есть еще один запросопция доступна.В этой ситуации поиск индекса может быть не быстрее сканирования таблицы, но, поскольку мы получаем только catergory_id, сканирование индекса (а не поиск индекса) может быть еще быстрее.Сканирование индекса читает каждую запись таблицы индекса, вместо того чтобы использовать преимущества древовидной структуры (что делает поиск индекса).Однако, поскольку запрашиваемая информация полностью содержится в индексе, доступ к таблице данных не потребуется.Сканирование индекса аналогично сканированию таблицы операцией O (n), но поскольку индекс обычно меньше таблицы, для сканирования индекса требуется меньше обращений к диску, чем для сканирования таблицы.

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

2 голосов
/ 06 декабря 2013

Для SQL Server не менее:

Сканирование индекса может быть быстрее, потому что, по-видимому, индекс не охватывает весь набор столбцов в таблице, в то время как сканирование таблицы (или кластеризованного индекса) должно считывать все данные. Если индекс включает все столбцы в таблице, то он должен быть примерно эквивалентен сканированию таблицы, и выбор между сканированием индекса и сканированием таблицы (или CIX) будет броском монеты. Разница в том, что когда у вас меньше столбцов в индексе, вы можете разместить больше строк индекса на странице размером 8 КБ, что приведет к уменьшению общего количества страниц, которые вам нужно прочитать, чтобы отсканировать все данные в индексе.

Чтобы проиллюстрировать, что я имею в виду, представьте, что у вас есть две копии телефонной книги: одна с фамилией, именем, почтовым адресом и номером телефона, а другая только с фамилией, именем и номером телефона. Теперь представьте, что, поскольку адрес улицы не нужно печатать, вы можете разместить два дополнительных столбца имен и телефонных номеров на любой странице телефонной книги. Конечным результатом этого является то, что телефонная книга тоньше, потому что вы можете разместить одинаковое количество телефонных номеров на меньшем количестве страниц. Далее, представьте, что вы обвинены в подсчете количества телефонных номеров в книге. Что бы вы выбрали: тот, в котором указан адрес улицы (который содержит больше страниц, аналогично сканированию таблицы), или тот, у которого нет адреса улицы (в котором меньше страниц, аналогично большинству сканированных индексов)? Я бы выбрал тот, на котором меньше страниц.

Другой недостаток в том, что некоторые индексы могут быть отфильтрованы, что означает, что они не только имеют меньше столбцов в большинстве случаев (и, следовательно, могут разместить больше строк на одной странице), но также могут иметь предложение WHERE, которое исключает много строк В этом случае также сканирование индекса будет лучше, чем сканирование таблицы (но это будет работать только для запросов, имеющих соответствующее предложение WHERE и ту же семантику).

2 голосов
/ 02 января 2012

Поскольку @danihp ответил на первую часть вопроса, я попытаюсь ответить на вторую «где она используется конкретно» .Это для Oracle, но это верно для большинства СУБД.

Предположим, у нас есть таблица my_table, которая уникально индексируется в столбце id и имеет второй индекс, который не является уникальным,в столбце yet_another_column:

create my_table ( id varchar2(20) not null
                , another_column not null
                , yet_another_column
                , constraint pk_my_table primary key (id) 
                );

create index i_my_table on my_table ( yet_another_column );

Теперь, если бы мы были select * from my_table where id = '1', это сделало бы / должно выполнить сканирование уникального индекса индекса pk_my_table.Затем мы повторно вводим таблицу, используя индекс, чтобы вернуть все в my_table, где id = '1'.

Если бы вместо этого был запрос select id from my_table where id = 'a', то нет необходимости во втором этапе, так каквсе значения, которые нам нужны, содержатся в индексе.В этом случае запрос будет выполнять только сканирование уникального индекса 1021 *.

Далее, если наш запрос будет select * from my_table where yet_another_column = 'y', то у нас будет индекс по столбцу, но он не уникален поэтому нам нужно просмотреть весь индекс, чтобы попытаться найти все значения, которые соответствуют нашему условию where, то есть просмотр индекса .Еще раз мы выбираем столбцы, которых нет в нашем индексе, поэтому нам нужно повторно войти в таблицу, чтобы получить их.

Наконец, если бы наш запрос был select id from my_table where another_column = 'yes'.У нас нет индекса для another_column, поэтому мы должны выполнить сканирование таблицы , чтобы найти значение, то есть мы должны найти все в таблице where another_column = 'yes'.

Теперь, возможно,Похоже, что в этих случаях нет особой разницы между просмотром таблицы и сканированием индекса.Нам все еще нужно найти значение в объекте в базе данных.Однако, так как индекс намного меньше и специально предназначен для сканирования (см. Другие ответы), обычно намного быстрее выполнить сканирование индекса , если вы хотите только небольшую часть строк втаблица .Если вы хотите сказать 10% таблицы, тогда этот пункт становится "это зависит".

...