Sql Server Устаревшая база данных в кластерный индекс или нет - PullRequest
6 голосов
/ 21 августа 2010

У нас есть устаревшая база данных, которая является сервером базы данных sql (2005 и 2008).

Все первичные ключи в таблицах являются уникальными идентификаторами.

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

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

Мы не можем удалить уникальный идентификатор, так как он используется для целей управления идентификацией записей удаленных сайтов.

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

т.е.

int identity - Первый столбец для поддержания скорости вставки уникальный идентификатор - чтобы приложение продолжало работать как положено.

Цель состоит в том, чтобы повысить производительность запросов идентификации и запросов к объединенным таблицам.

В1: Повысит ли это производительность запросов к БД или замедлит ее?

Q2: Есть ли альтернатива этому, которого я не перечислил?

Спасибо Пит

Редактировать: Проблемы с производительностью связаны с быстрым извлечением данных с помощью операторов выбора, особенно если несколько более «транзакционных / изменяющихся» таблиц объединены вместе.

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

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

Я больше склоняюсь к добавлению дополнительного столбца идентификаторов в каждую из таблиц с высокой нагрузкой, а затем к включению текущего столбца Guid PK в кластеризованный индекс, чтобы обеспечить наилучшую производительность запросов.

Редактировать 3: Я бы оценил, что 80% запросов выполняются только по первичным и внешним ключам через механизм доступа к данным. Как правило, наша модель данных имеет лениво загруженные объекты, которые выполняют запрос при обращении к ним, эти запросы используют идентификатор объекта и столбец PK. У нас есть большое количество пользовательских запросов на исключение / включение данных, которые используют столбцы внешнего ключа в качестве фильтра, основанные на критериях для типа X, исключая следующие идентификаторы. Оставшиеся 20% - это когда в столбцах Enum (int) или в диапазоне дат содержатся предложения, в системе выполняется очень мало текстовых запросов.

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

Ответы [ 4 ]

4 голосов
/ 21 августа 2010

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

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

У вас есть поле, которое часто используется для сканирования диапазона?Какие столбцы используются для объединений?Существует ли комбинация столбцов, которая также однозначно идентифицирует строку помимо GUID?Размещение образца модели данных поможет нам предложить хорошего кандидата для кластеризации.

2 голосов
/ 21 августа 2010

Я не уверен, откуда берутся ваши GUID, но если они генерируются во время вставки, используя NEWSEQUENTIALID () в SQL Server вместо NEWID () поможет вам избежать проблем фрагментации во время вставки.

Относительно выбора кластерного индекса, поскольку Кимберли Л. Трипп заявляет здесь : «наиболее важные факторы при выборе кластеризованного индекса заключаются в том, что онуникальный, узкий и статичный (постоянно увеличивающийся имеет другие преимущества для минимизации расколов). "GUID не соответствует узкому требованию по сравнению с INT или даже BIGINT.

Кимберли также имеет отличную статью о GUID в качестве ПЕРВИЧНЫХ КЛЮЧЕЙ и / или ключа кластеризации .

1 голос
/ 21 августа 2010

Мне не на 100% ясно: ваш шаблон доступа номер 1 для запроса таблиц по GUID или другим столбцам? А при объединении с другими таблицами какие столбцы (и типы данных) используются чаще всего?

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

UPDATE

Теперь, когда я знаю немного больше, у меня есть сумасшедшее предложение. Сгруппируйте эти таблицы по GUID, но установите коэффициент заполнения равным 60%. Это улучшит проблему разделения страниц и повысит производительность запросов к этим щенкам.

Что касается использования Guid.NewGuid (), то кажется, что вы все равно можете делать последовательные GUID в C #. Я нашел следующий код здесь на SO:

[DllImport("rpcrt4.dll", SetLastError = true)]
static extern int UuidCreateSequential(out Guid guid);

public static Guid SequentialGuid()
{
    const int RPC_S_OK = 0;
    Guid g;
    if (UuidCreateSequential(out g) != RPC_S_OK)
        return Guid.NewGuid();
    else
        return g;
}

newsequentialID () на самом деле является просто оболочкой для UuidCreateSequential. Я уверен, что если вы не можете использовать это непосредственно на клиенте, вы можете найти способ сделать быстрый обход на сервер, чтобы получить оттуда новый последовательный идентификатор, возможно, даже с таблицей "распределителя" и хранимая процедура для выполнения работы.

0 голосов
/ 21 августа 2010

Вы не указываете свои проблемы с производительностью. Если худшее действие - ВСТАВКА, то, возможно, ваше решение верное. Если это что-то еще, то я бы посмотрел, как кластерный индекс может помочь в этом.

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

...