@sibvic

Какая структура базы лучше всего подойдет для получения новых записей из базы?

Возник вопрос, как лучше всего организовать структуру базы/таблицы для наиболее быстрого получения новых записей. Имеется таблица в которую постоянно добавляются новые записи. Помимо основных данных в таблице есть 2 поля:
Processed и RecordType (nullable). Для этих полей создан неуникальный индекс.

Есть несколько исполнителей которые выгребают новые записи из таблицы.

SELECT ...
FROM [Table] AS [a]
WHERE ([a].[Processed] = 0) AND ([a].[RecordType] IS NULL OR ([a].[RecordType] = @__Type_0))

SELECT ...
FROM [Table] AS [a]
WHERE (([a].[Processed] = 0) AND [a].[RecordType] IS NOT NULL) AND ([a].[RecordType] = @__Type_0)


Обычно необработанных записей в таблице - единыцы. Все остальное - история, и запрашивается чрезвычайно редко.
И загвоздка в том, что первый запрос выполняется намного быстрее второго (в десятки-сотни раз). И чем больше истории в таблице, тем медленнее он исполняется. Исправление на WHERE (([a].[Processed] = 0) AND [a].[RecordType] = @__Type_0) не исправляет ситуацию.
И в связи с этим у меня два вопроса:
1) Почему второй запрос такой медленный? Похоже что запрос не использует индекс, но непонятно почему.
2) Не лучше ли будет сделать отдельную таблицу для необработанных записей, и потом их переносить в таблице истории? Или есть какой-то другой трюк?

Пробовал на Azure DB и на локальном MS SQL Local DB, если это имеет значение.
  • Вопрос задан
  • 48 просмотров
Решения вопроса 1
@sibvic Автор вопроса
Похоже опять сработала методология Rubber Duck Programming. В моем случае помог фильтр на индекс
Индекс
CREATE NONCLUSTERED INDEX [IX_...]
    ON [dbo].[Table]([Processed] ASC, [RecordType] ASC);

изменил на
CREATE NONCLUSTERED INDEX [IX_...]
    ON [dbo].[Table]([Processed] ASC, [RecordType] ASC) WHERE ([Processed]=(0));

Ну либо в EF:
protected override void OnModelCreating(ModelBuilder builder)
        {
            base.OnModelCreating(builder);
            builder.Entity<Table>()
                .HasIndex(x => new { x.Processed, x.RecordType})
                .HasFilter("Processed= 0")//NEW!!!
                .IsUnique(false);
        }


Теперь оба запроса выролняются одинаково быстро
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
tsklab
@tsklab
Системный администратор, программист
Потому что оптимизатор включает запрос по индексу. Посмотрите план выполнения.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через TM ID
Похожие вопросы
от 120 000 до 220 000 руб.
Hunt4You Севастополь
от 60 000 до 120 000 руб.
Optimizon Ростов-на-Дону
До 100 000 руб.