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

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

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