Какое ключевое слово DDL создает индекс в Microsoft SQL Server?

У меня есть оператор SQL создания таблицы со следующим столбцом:

status_id tinyint not null,

Есть ли какое-либо дополнительное ключевое слово, чтобы сделать его индексированным столбцом?

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

Thom A 05.08.2024 16:33

@ThomA, у меня есть другие колонки. У меня есть внешние ключи, и я знаю, что они автоматически индексируются. У меня также есть уникальные столбцы, которые, как я знаю, автоматически индексируются. Этот вопрос касается столбцов, которые не являются ни уникальными, ни внешними ключами.

ilhan 05.08.2024 16:35

Вам нужно использовать отдельный оператор создания индекса, синтаксис примерно такой: Create nonclustered index IX_someName ON tableName (status_id)

siggemannen 05.08.2024 16:39

Тебе «не обязательно», @siggemannen.

Thom A 05.08.2024 16:45

Ого, @ThomA, мне нужно обновить свой внутренний синтаксис sql, спасибо :D

siggemannen 05.08.2024 16:46

Внешние ключи не индексируются автоматически

Martin Smith 05.08.2024 18:07

Чего не хватало в официальной документации, что требовало здесь вопроса?

Dale K 05.08.2024 18:47

@DaleK — либо ключевое слово DDL, которое помечает столбец как индекс, либо удобную для пользователя документацию.

ilhan 06.08.2024 01:24

@DaleK, если вы укажете официальную документацию, удобную для человека. Плюс как вы это нашли с помощью поисковика, то я удалю свой вопрос.

ilhan 06.08.2024 02:16

(Почти, если не вся) Документация по SQL Server включает раздел синтаксиса, ilhan, поэтому поиск «CREATE TABLE SQL SERVER » (по крайней мере для меня) дает документацию в качестве второго результата (потому что w3schools.. .), и там вы можете увидеть полный синтаксис, который показывает, как встроить индекс столбца.

Thom A 06.08.2024 10:31
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
1
10
99
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

В ответ на ваш вопрос; да, вы можете встроить INDEX столбец. Синтаксис такой же, как при встраивании CONSTRAINT:

CREATE TABLE dbo.MyTable (MyID int IDENTITY CONSTRAINT PK_MyTable PRIMARY KEY,
                          MyColumn varchar(30) NOT NULL,
                          MyStatus tinyint NOT NULL INDEX IX_MyTable_MyStatus,
                          MyDate date NOT NULL CONSTRAINT DF_MyTable_MyDate DEFAULT (SYSDATETIME()));

Однако единственная проблема заключается в том, что INDEX включен только MyStatus, поэтому он может оказаться бесполезным.

Представьте себе запрос, подобный следующему:

SELECT MyID,
       MyColumn,
       MyDate
FROM dbo.MyTable
WHERE MyStatus = 0;

INDEXIX_MyTable_MyStatus здесь не пригодится. Это связано с тем, что индекс не включает ни один из других столбцов, возвращаемых в SELECT (кроме MyID, поскольку он включен неявно, поскольку это индекс CLUSTERED). В лучшем случае индекс можно использовать для поиска с последующим поиском по ключу, но это быстро становится дорогостоящим. Было бы неудивительно увидеть сканирование таблицы (и именно это и происходит, см. Связанную скрипту в конце этого ответа).

Таким образом, вам было бы гораздо лучше определить INDEX в конце и добавить соответствующий INCLUDE:

CREATE TABLE dbo.MyTable (MyID int IDENTITY CONSTRAINT PK_MyTable PRIMARY KEY CLUSTERED,
                          MyColumn varchar(30) NOT NULL,
                          MyStatus tinyint NOT NULL,
                          MyDate date NOT NULL CONSTRAINT DF_MyTable_MyDate DEFAULT (SYSDATETIME()),
                          INDEX IX_MyTable_MyStatus (MyStatus) INCLUDE (MyColumn,MyDate));

db<>поиграться с планами запросов

Почему INDEX IX_MyTable_MyStatus бесполезен, я знаю, что он не охватывает, но разве он все еще не полезен в части, где? Я спрашиваю, потому что не знаю, как SQL Server работает с индексами.

Ergest Basha 05.08.2024 17:04

Если вы проверите связанный скрипт БД @ErgestBasha , который показывает план запроса, вы увидите, что ответ на вопрос «разве он все еще не полезен в части, где» — нет. SQL Server даже не удосуживается выполнить поиск, за которым следует поиск ключа. Индексы по отдельным столбцам редко бывают полезны, если только вы не собираетесь часто выполнять запросы с очень узкой областью действия или UNIQUE INDEX.

Thom A 05.08.2024 18:03

В приведенном выше примере только если я изменю количество строк со статусом 1 на 1 из ~750, поиск по ключу будет использоваться при поиске строк со значением 1: db<>fiddle. И при значении 0 очевидно, что скан все равно намного лучше.

Thom A 05.08.2024 18:08

Самое основное утверждение:

create index [some name] on [table name] ([column(s)])

Это создаст именованный индекс в таблице, указанной для перечисленных столбцов. Внимание: нежелательно, чтобы слишком много столбцов было индексировано. Если это для MS SQL Server, то онлайн-справка по create index обширна.

Вы можете добавить ряд «улучшений», например CLUSTERED, UNIQUE.

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

Я знаю, что есть команда create index, но это ненужная дополнительная команда. Я имею в виду, что это выглядит некрасиво.

ilhan 06.08.2024 02:02

Похоже, ваше представление о том, как работают индексы, ошибочно. Идея иметь отдельный индекс для каждого столбца, который может использоваться в предикате запроса, неверна. Редко бывает полезно иметь индекс только для одного столбца.

Чтобы улучшить ваше понимание индексов, рассмотрите таблицу Person со столбцами для FirstName, LastName и Email.

Вы хотите найти адрес электронной почты John Smith, поэтому пишете такой запрос:

SELECT Email FROM Person WHERE FirstName = 'John' AND LastName = 'Smith'

Но запрос медленный. Итак, с вашим текущим пониманием, вы добавляете индекс для FirstName и еще один отдельный индекс для LastName и снова запускаете запрос.

Теперь запрос, вероятно, стал несколько быстрее... но он еще не идеален. Один из индексов был потрачен впустую и вообще не использовался запросом. Запрос может проверять только индекс FirstName или индекс LastName. Он не может использовать оба в одном проходе по таблице. Более того, запросу потребуется ссылаться на таблицу для каждого результата из индекса. Если он использовал индекс LastName, он все равно должен свериться с исходной таблицей, чтобы увидеть, соответствует ли значение FirstName, и получить Email.

Этого достаточно, в зависимости от таких факторов, как размер таблицы, чтобы база данных могла даже выбрать сканирование таблицы вообще без использования индекса.

Мы можем добиться большего. Давайте сделаем шаг вперед и построим ОДИН индекс по двум столбцам:

LastName, FirstName

Порядок имеет значение! В зависимости от избирательности LastName и FirstName вы также можете изменить порядок этих столбцов. Теперь мы почти уверены, что база данных будет использовать этот индекс для запроса, что определенно будет намного быстрее. Теперь запрос сможет эффективно определять, какие строки ему нужны, и может возвращаться к исходной таблице только по этим строкам, чтобы найти столбец Email.

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

Но только для этого запроса давайте сделаем еще один шаг и построим индекс для использования всех трех столбцов, например:

 LastName, FirstName, Email

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

Но есть последний шаг, который нужно сделать:

 LastName, FirstName INCLUDE Email

Здесь мы используем INCLUDE для адреса электронной почты, чтобы сообщить базе данных, что ей не нужно сортировать Email значения внутри индекса. Это повышает эффективность, поскольку, если вы измените свой адрес электронной почты, для поддержания индекса теперь базе данных нужно будет только изменить значение в индексе; НЕ нужно перемещать строку.

«Ваше представление о том, как работают индексы, ошибочно» Моя ошибочная вещь — это мой опыт написания DDL вручную для Microsoft SQL Server, который включает ключевое слово для индекса. В противном случае я использую многостолбцовый индекс, о котором вы упоминаете, как минимум 10 лет.

ilhan 06.08.2024 01:55

Другие вопросы по теме