Основной источник событий в SQL Server с использованием индексированных представлений
Я пытаюсь реализовать очень простой Event Sourcing, используя SQL Server. Никаких библиотек, никаких других серверов, ничего особенного, только из основ использования SQL Server.
Предположим, у меня есть эта таблица:
Id | Name | Data | CreatedOn
1 | Fruit | Apple | <DATE_TIME> Apr 1, 2015
2 | Fruit | Peach | <DATE_TIME> Apr 5, 2015
3 | Fruit | Mango | <DATE_TIME> Apr 10, 2015
4 | Vegetable | Potato | <DATE_TIME> May 20, 2015
5 | Vegetable | Tomato | <DATE_TIME> May 30, 2015
Теперь я хочу создать представление, которое показывает мне последние данные, сгруппированные по имени, так что результат будет следующим:
Id | Name | Data | CreatedOn
3 | Fruit | Mango | <DATE_TIME> Apr 10, 2015
4 | Vegetable | Tomato | <DATE_TIME> May 30, 2015
Достаточно просто, CREATE VIEW Latest AS SELECT t1.* FROM table t1 JOIN (SELECT TOP 1 Id FROM table ORDER BY CreatedOn DESC, Id DESC) t2 ON t2.Id = t1.Id;
Теперь у меня будет много миллионов строк в таблице и много одновременных операций чтения в представлении. Поэтому я хотел бы проиндексировать его (индексированные представления SQL Server). Кажется, мне здесь не повезло, так как индексированные представления не могут содержать производные таблицы ИЛИ TOP ИЛИ MAX ИЛИ самостоятельных соединений.
Любые мысли о том, как я мог бы создать индексированное представление?
Если это невозможно, я мог бы использовать триггер INSTEAD OF, который обновляет столбец IsLatest BIT в таблице, и создать индексированное представление на основе этого фильтра.
Любые другие предложения?
1 ответ
Ваше существующее представление не сработало бы, потому что SELECT TOP 1 Id FROM table ORDER BY CreatedOn DESC, Id DESC
возвращает только одну строку, но вам понадобится одна для каждой внешней строки.
Этот запрос не может быть материализован с индексированным представлением. Даже если вы переформулируете запрос следующим образом:
select *
from T t1
join (
select Name, MAX(ID) as MaxID
from T
group by Name
) t2 on t1.name = t2.Name and t1.ID = t2.MaxID
Вы не можете материализовать какую-либо значимую часть этого. Обычно этот шаблон может быть использован для group by
часть, но здесь MAX агрегированный предотвращает это. И это имеет смысл, потому что трудно поддерживать индексированное представление и сохранять какое-то максимальное значение точным при наличии удалений или обновлений (вставки просты).
Ваши варианты:
- Правильно индексировать базовую таблицу.
- Вручную поддерживать денормализованную версию данных.