@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, если это имеет значение.
  • Вопрос задан
  • 58 просмотров
Решения вопроса 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
Системный администратор, программист
Потому что оптимизатор включает запрос по индексу. Посмотрите план выполнения.
Ответ написан
Ваш ответ на вопрос

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

Войти через центр авторизации
Похожие вопросы