Поиск в базе данных / словарные таблицы - проблема разработки - жесткое кодирование GUID - PullRequest
1 голос
/ 05 апреля 2011

Ниже возник вопрос в моей голове при рефакторинге сложной хранимой процедуры, которая была узким местом в моей базе данных ... Позвольте мне представить эту тему.Предположим, у нас есть таблица поиска / словарь (она содержит GUID в качестве внешнего ключа для других таблиц и имя, удобное для чтения человеком):

CREATE TABLE [dbo].[PlayerStatus](
    [PlayerStatusId] [uniqueidentifier] NOT NULL,
    [PlayerStatusName] [nvarchar](50) NOT NULL,
 CONSTRAINT [PK_PlayerStatus] PRIMARY KEY CLUSTERED 
(
    [PlayerStatusId] ASC
))

и есть таблица Player :

    CREATE TABLE [dbo].[Player](
[PlayerId] [uniqueidentifier] NOT NULL,
[PlayerStatusId] [uniqueidentifier] NOT NULL,
[PlayerName] [nchar](10) NOT NULL, 
[PlayerSurname] [nchar](10) NOT NULL, 
CONSTRAINT [PK_Player] PRIMARY KEY CLUSTERED  ( [PlayerId] ASC )) ON [PRIMARY]

Довольно просто.

Скажем, где-то в коде есть огромный запрос, который обращается ко множеству таблиц:

SELECT ...
FROM Player JOIN PlayerStatus ON Player.PlayerStatusId = PlayerStatus.PlayerStatusId
.....
WHERE PlayerStatus.PlayerStatusName = 'Active' ....

Теперь, в моей хранимой процедуре, согласнок плану выполнения Игроки таблица была включена в набор результатов в начале.Если предположить, что это очень большая таблица с миллионами строк, хеш-соединение между Player и PlayerStatus может занять много времени.Оптимизировав этот запрос, я мог бы переписать его примерно так:

SELECT ...
FROM Player .....
WHERE PlayerStatus.PlayerStatusId = '46bb6a12-4cd9-4b6c-84c2-7444f5f45eb6' ....

И это именно то, что я сделал в своей процедуре с узким местом.Таким образом, я удалил 4 похожих таблицы поиска / словаря, которые содержали различные типы статусов.К моему удивлению, мне удалось повысить производительность на 50%, хотя я думал, что такие таблицы не повлияют на производительность вообще.Но это побочный сюжет.У меня вопрос: Что вы думаете о жестких инструкциях?

РЕДАКТИРОВАТЬ

  • У меня есть PK-индексы на PlayerStatus.PlayerStatusId иPlayer.PlayerId
  • У меня есть ограничение FK на Player.PlayerStatusId:

ALTER TABLE [dbo]. [Player] С ПРОВЕРКОЙ ДОБАВИТЬ КОНСТРАКТ [FK_Player_PlayerStatus] FOREIGN KEY[PlayerStatusId]) ССЫЛКИ [dbo]. [PlayerStatus] ([PlayerStatusId])

  • Таблица Player содержит около 2 млн записей, таблица PlayerStatus содержит около 25 записей

Ответы [ 3 ]

1 голос
/ 05 апреля 2011

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

1 голос
/ 05 апреля 2011

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

Ваш пример довольнопросто, но если у вас более сложный запрос с множеством объединений, удаление одного объединения может ускорить запрос.Примером в вашем коде будет удаление объединения с PlayerStatus и фильтрация с помощью PlayerStatusID из таблицы Player вместо использования PlayerStatusName из PlayerStatus.

Есть еще две вещи, которые следует учитывать, когда речь идет о жестком кодировании GUID / ID:

  1. GUID / ID - это обычно PK в таблице, на который ссылается FK, поэтому изменить GUID / ID труднее, чемэто изменить то есть название статуса.Изменение PlayerStatusName в вашем примере с «Active» на «In action» сделает ваш запрос с помощью PlayerStatusName бесполезным.Таким образом, использование идентификаторов GUID / идентификаторов гарантирует, что запросы основаны на сплошных столбцах (PK, FK)
  2. Использование идентификаторов GUID / ID в запросах требует небольшой дисциплины, например, если у вас несколько сред.Необходимо убедиться, что соответствующие идентификаторы в таблицах со словарями (т. Е. PlayerStatus) одинаковы во всех экземплярах базы данных.
1 голос
/ 05 апреля 2011

Ответ. Не задавайте GUID жестко.Это приводит к тому, где критерии?В таблице состояния.Как это указать?Если строка неизменна, хорошо, используйте ее, если хотите, я предпочитаю логический флаг IsActive.Если производительность неприемлема, вернитесь - используя информацию, которую мы обсуждали

Есть ли у вас ограничение внешнего ключа?

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

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

Ограничения - ваш друг.

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

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

Кроме того, у меня обычно есть логический столбец, такой как IsActive в статусе, поскольку у вас может быть несколько «состояний», которые равныЛогически, при определенных обстоятельствах, например, Status IN («Закрыто», «Заблокировано», «Приостановлено», «') => IsInactive = 1, в то время как только (« Заблокировано ») => IsLocked = 1. Я хочу, чтобыиспользовать одну строку состояния, но использовать физические флаги для отдельных состояний в учетных записях, а затем их логические комбинации в качестве логических флагов для критериев запроса.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...