2014-09-12 2 views
2

Я читал в последнее время о том, как работает clustered index и non-clustered index. Мое понимание в простых терминах (поправьте меня, если ошибаюсь):Оптимизация запросов на основе кластеризованных и некластеризованных индексов в SQL?

Структура данных, поддерживает clustered и non-clustered index является B-Tree

Clustered Index: физически сортирует данные, основанные на колонке (или ключ). вы можете получить только один номер clustered Index за table. Если во время создания таблицы не указывается index, сервер SQL автоматически создаст clustered Index на primary key column.

Q1: Поскольку данные физически сортируются по индексу, здесь не требуется дополнительное пространство. это верно? так что происходит, когда я бросаю индекс, который я создал?

Non-clustered Index: В non-clustered indexes дерево leaf-node содержит значения столбцов и указатель (указатель строки) к фактической строке в базе данных. Здесь есть дополнительное пространство, необходимое для хранения этого non-clustered index table физически на диске. Однако один из них не ограничен номером non-clustered Indexes.

Q2: Означает ли это, что запрос на некластеризованный индексный столбец не приведет к сортировке данных?

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

Excercise:

рассмотрит Employee таблицы:

CREATE TABLE Employee 
(
PersonID int PRIMARY KEY, 
Name varchar(255), 
age int, 
salary int 
); 

Теперь я создал таблицу сотрудников (создаются кластерный индекс по умолчанию на сотруднике).

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

, например:

select * from employee where age > XXX; 

select * from employee where salary > XXXX and salary < YYYY; 

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

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

спасибо Сообщения, которые я прочитал здесь:

http://javarevisited.blogspot.com/2013/08/difference-between-clustered-index-and-nonclustered-index-sql-server-database.html

http://msdn.microsoft.com/en-us/library/ms190457.aspx

Clustered vs Non-Clustered

What do Clustered and Non clustered index actually mean?

What are the differences between a clustered and a non-clustered index?

How does database indexing work?

+0

Вы отметили этот вопрос [tag: mysql], но ваши вопросы подразумевают, что вы спрашиваете о Microsoft SQL Server. Что он? Оба продукта предоставляют кластерные и некластеризованные индексы, но внутренние детали могут немного отличаться. Можете ли вы прояснить и, если необходимо, изменить теги? –

+0

@BillKarwin: Я не спрашиваю о сервере Microsoft SQl. Я хочу, чтобы это был общий вопрос. Интерактивная реализация индексов может различаться между mysql и Microsoft. но меня интересует концепция/идея того, как она работает. Я не уверен, какая часть вопроса указывает сервер Microsoft SQL, если это так, любезно отредактируйте его. Я новичок здесь, поэтому я мог бы бессознательно перефразировать терминологию. Благодаря! –

ответ

3

Для SQL Server

Q1 Дополнительное пространство требуется только для кластерного индекса, если он не является уникальным. SQL Server добавит 4-байтовый уникальный идентификатор к уникальному кластерному индексу. Это связано с тем, что он использует кластерный ключ как rowid в некластеризованных индексах.

Q2 Некластеризованный индекс можно прочитать по порядку. Это может помочь запросам, в которых вы указываете заказ. Он также может сделать привлекательные объединения. Это также поможет с запросами диапазона (x < col и y> col).

Q3 SQL Server выполняет дополнительный поиск по закладкам при использовании некластеризованного индекса. Но это только если ему нужен столбец, который не находится в индексе. Заметим также, что вы можете добавить дополнительные столбцы в уровне листа индексов. Если индекс можно использовать без дополнительного поиска, он называется индексом покрытия.

Если требуется поиск по закладкам, он не занимает большого процента строк, пока не будет быстрее сканировать весь кластерный индекс. Уровень зависит от размера строки, размера ключа и т. Д. Но 5% строк является типичным отключением.

Q4 Если самая важная вещь в вашем приложении было сделать оба эти запросы как можно быстрее, вы можете создать индекс покрытия на них обоих:

create index IX_1 on employee (age) include (name, salary); 
create index IX_2 on employee (salary) include (name, age); 

Примечание Вы не должны специально включают ключ кластера, поскольку некластеризованный индекс имеет его как указатель строки.

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


Подробнее об этом продукте. Представьте себе, что вы и не уникальный кластеризованный индекс по возрасту, и некластеризованный индекс зарплаты. Скажем, у вас были следующие строки:

age | salary | uniqifier 
20 | 1000 | 1 
20 | 2000 | 2 

Тогда индекс заработной платы будет размещать строки, как так

1000 -> 20, 1 
2000 -> 20, 2 

Допустим, вы запустили запрос select * from employee where salary = 1000, и оптимизатор решил использовать индекс заработной платы. Затем он найдет пару (20, 1) из поиска индекса, а затем просмотрит это значение в основных данных.

+0

Thats за усилия, чтобы помочь здесь. не могли бы вы рассказать свою точку зрения на Q1. Что касается Q2) выбор запроса в некластеризованном индексе приведет к упорядоченному порядку, только если я укажу 'ORDER BY'. (Из выше этого ответа). По кластерному индексу он сортируется по умолчанию. так что есть дополнительный процесс сортировки в случае некластеризованных индексов правильно? поэтому операция с диапазоном («возраст <30 и возраст> 60») окажется неэффективной в некластеризованных индексах. пожалуйста, объясните –

+0

+1 хорошо, чтобы привести примеры того, как Microsoft отличается от MySQL. Индексные реализации не универсальны. Фактически, стандарт ANSI/ISO SQL вообще не упоминает индексы, поэтому все реализации являются расширениями поставщиков SQL! –

+0

некластеризованный индекс по-прежнему является b-деревом, поэтому вы можете читать индексные страницы по порядку.Представьте себе, хотите ли вы узнать, сколько людей было в возрасте от 10 до 20 лет. Вы найдете 10 в btree, а затем пройдете по порядку, пока не получите до 20, считая каждую строку при прохождении. – Laurence

5

Я не знаю о внутренних компонентах Microsoft SQL Server, но могу ответить на MySQL, который вы отметили для своего вопроса. Детали могут отличаться для других реализаций.

Q1. Правильно, дополнительное пространство не требуется для кластерного индекса.

Что произойдет, если вы сбросите кластеризованный индекс? MySQL InnoDB engine всегда использует первичный ключ (или первый ненулевой уникальный ключ) в качестве кластеризованного индекса. Если вы определяете таблицу без первичного ключа или отбрасываете первичный ключ существующей таблицы, InnoDB generates an internal artificial key for the clustered index. Этот внутренний ключ не имеет логического столбца для ссылки на него.

Q2. Порядок строк, возвращаемых запросом, который использует некластеризованный индекс, не гарантируется. На практике это порядок доступа к строкам. Если вам нужны строки для возврата в определенном порядке, вы должны использовать ORDER BY в своем запросе. Если оптимизатор может сделать вывод о том, что ваш желаемый порядок совпадает с порядком, в котором он будет обращаться к строкам (индексный порядок, будь то кластеризованным или некластеризованным индексом), тогда он может пропустить шаг сортировки.

Q3. Некластеризованный индекс InnoDB не имеет указателя на соответствующую строку на листе индекса, он имеет значение значение первичного ключа. Таким образом, поиск в некластеризованном индексе - это действительно два поиска B-дерева, первый - поиск листа некластеризованного индекса, а затем второй поиск в кластерном индексе.

Это двойная стоимость одного поиска по B-дереву (более или менее), поэтому у InnoDB есть дополнительная функция, называемая Adaptive Hash Index. Часто используемые значения получают кеширование в AHI, и в следующий раз, когда запрос выполняет поиск кешированного значения, он может выполнять поиск O (1). В кеше AHI он находит указатель непосредственно на лист кластерного индекса, поэтому он исключает и поиск B-деревьев, часть времени.

Насколько это повышает общую производительность, зависит от того, как часто вы выполняете поиск тех же самых значений, которые были просмотрены ранее. По моему опыту, это типично для отношения поиска хешей против не-хэш-запросов примерно 1: 2.

Q4. Постройте индексы для обслуживания запросов, которые необходимо оптимизировать. Обычно кластерный индекс является основным или уникальным ключом, и, по крайней мере, в случае InnoDB это требуется. Ни age, ни salary, скорее всего, будут уникальными.

Возможно, мне понравилась моя презентация, How to Design Indexes, Really.

Q5. InnoDB автоматически создает индекс при объявлении уникального ограничения. У вас не может быть ограничения без существующего для него индекса. Если у вас не было индекса, как механизм обеспечит уникальность при вставке значения? Он должен будет искать всю таблицу для дублирования значения в этом столбце. Индекс помогает сделать уникальные проверки намного эффективнее.

+0

Спасибо за отличное объяснение. относительно Q3: вы упомянули, что будут выполняться два поиска по дереву, но чтобы найти правильную строку, у меня будет три блока чтения (и каждый блок может иметь 10 строк до 100 в зависимости от размера блока). Так что, теоретически, даже если у меня есть идентификатор первичного ключа, мне нужно прочитать весь блок, пропустите его, пока я не найду идентификатор интереса. Это верно? –

+0

Если у вас есть youtube или любая видеопрезентация вашего разговора, это было бы здорово. Я смотрю на слайды, и они просто потрясающие !! –

+1

Правильно. Например, InnoDB хранит все на страницах одинакового размера (по умолчанию 16 КБ). Некоторое количество строк соответствует одной странице. Но как только он загружает страницу в память, накладные расходы на ее поиск незначительны. I/O для загрузки страницы с диска примерно в 100 000 раз дороже. –

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