Как ускорить работу View (в MS SSQL)?
От: SteeLHeaD  
Дата: 06.12.15 19:15
Оценка:
Здравствуйте.

Попробую словами, без кода, объяснить свою проблему.
Есть бизнес — объект, называемый Order. Каждый его экземпляр хранится в строке таблицы Orders.
В нем около 150 полей, значительная часть (около половины) из которых — это id элементов справочников (перечислений).
Чтобы сделать объект "доступным для отображения" есть View, которая называется OrdersView.
Исторически сложилось, что в самом начале в объекте было гораздо меньше полей,
потом новые поля добавлялись в объект, в таблицу(как NULLable поля) и во View (как LEFT OUTER JOIN).
И по всему этому хозяйству надо делать всякие сложные поиски, которые формулируются в терминах полей,
которые выдает View.
Со временем, по мере увеличения кол-ва полей, кол-ва справочников и кол-ва записей в таблицу Orders —
поиск работал все более медленно. В попытках ускорить его я попытался построить индексы по полям View.
И столкнулся с тем, что для View, использующего Left Outer Join — это невозможно
(получаю ошибку "Cannot create index on view "Test.dbo.OrdersView" because it uses a LEFT, RIGHT, or FULL OUTER
join, and no OUTER joins are allowed in indexed views. Consider using an INNER join instead.").

Теперь у меня есть несколько выходов, я вижу такие:
1) отказываеться от использования Left Outer Join (что фактичеси потребует, чтобы у меня в строках таблицы не было
NULL — значений, ну и вообще потребует некоторого изменения логики на уровне извлечения и записи данных).

2) перейти на SQL — базу данных, которая не обладает таким странным ограничением на одновременное использование LEFT OUTER
JOIN и индексирование полей View (например, на одну из версий Oracle)

3) Отказаться в этой задаче от реляционной базы вообще, и использовать какую нибудь нереляционную, например, MongoDB.
Фактически этот объект Order — это документ, у которого много полей. Похоже на то, что его удобно хранить в
документно — ориентированной базе.

Как Вы посоветуете мне решать эту проблему — хранения вообще и медленного поиска в частности?
Re: Как ускорить работу View (в MS SSQL)?
От: wildwind Россия  
Дата: 06.12.15 21:43
Оценка: +1
Здравствуйте, SteeLHeaD, Вы писали:

SLH> Как Вы посоветуете мне решать эту проблему — хранения вообще и медленного поиска в частности?


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

И еще посоветую найти и прочитать, что же на самом деле означает "построить индексы по полям View" и откуда берутся ограничения.
Я привык, что в интернете можно найти ответ на любой вопрос. Я не люблю думать. Зачем думать, если всё уже придумано до меня? © Zenden@RSDN ::: avalon/1.0.442
Re: Как ускорить работу View (в MS SSQL)?
От: VladCore  
Дата: 06.12.15 22:36
Оценка:
Здравствуйте, SteeLHeaD, Вы писали:

SLH>Здравствуйте.


Не помню на какой-то старой Платформе (конференция) был целый доклад о том что СХЕМУ бд надо проектировать в соответствии с запросами приложения.

А вы спрашиваете как поправить схему БД в соответствии с тормозами запросов.

Никак
Отредактировано 06.12.2015 22:39 VladCore . Предыдущая версия .
Re: Как ускорить работу View (в MS SSQL)?
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 08.12.15 00:04
Оценка:
Здравствуйте, SteeLHeaD, Вы писали:

SLH>Как Вы посоветуете мне решать эту проблему — хранения вообще и медленного поиска в частности?

Тебе нужны индексы на таблицу orders по полям с максимальной селективностью

Если у тебя сценарий вроде подбора товара и интернет-магазине, то лучше сделать на движке полнотекстового поиска, который поддерживает предикаты.
Re: Как ускорить работу View (в MS SSQL)?
От: MasterZiv СССР  
Дата: 08.12.15 09:02
Оценка: +2
Здравствуйте, SteeLHeaD, Вы писали:

И здесь ты...

150 join-ов -- не криминал, если всё сделано правильно.
Индексируй таблицы, а не VIEW.
Если совсем невмоготу, выбрасывай VIEW, заменяй процедурой.
Вообще, там в использовании VIEW туча нюансов, но в принципе, view -- убийцы производительности,
и с ними достаточно трудно работать в смысле оптимизации. Но, подчёркиваю, в твоём конкретном случае
это может быть не так.

О конкретном случае: ты о нём говоришь ровно 0 слов, никакой информации.
А оптимизировать нужно и можно только конкретный случай, абстрактной оптимизации не
бывает. Это в твоём случае VIEW + ЗАПРОС, который его использует, да ещё и с
параметрами, которые есть в запросе и с данными в таблицах.



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


Сложные поиски и без VIEW уже могут быть проблемой.


И столкнулся с тем, что для View, использующего Left Outer Join — это невозможно
(получаю ошибку "Cannot create index on view "Test.dbo.OrdersView" because it uses a LEFT, RIGHT, or FULL OUTER
join, and no OUTER joins are allowed in indexed views. Consider using an INNER join instead.").


Ну, логично. Кстати, ещё не может быть фильтров по полям таблицы, которая в LEFT JOIN.


Теперь у меня есть несколько выходов, я вижу такие:
1) отказываеться от использования Left Outer Join .


Нет.

2) перейти на SQL — базу данных, которая не обладает таким странным ограничением на одновременное использование LEFT OUTER
JOIN и индексирование полей View


Нет такой базы, я подозреваю. К тому же тебе не нужно индексировать VIEW, это почти бесполезно.

3) Отказаться в этой задаче от реляционной базы вообще, и использовать какую нибудь нереляционную, например, MongoDB.

Это вообще бред. Кстати, типичный для "неосиляторов РСУБД". В NOSQL такие же данные, и такие же по ним индексы.
Ровно такие же.


Как Вы посоветуете мне решать эту проблему — хранения вообще и медленного поиска в частности?


Ну тут ничего конкретного нет в виде вопросов, поэтому ничего конкретного посоветовать нельзя.
Даже задача по сути неясна, только вопли ужоса... Так что только всё то, что было уже написано.
Re: Как ускорить работу View (в MS SSQL)?
От: BlackEric http://black-eric.lj.ru
Дата: 08.12.15 09:12
Оценка:
Здравствуйте, SteeLHeaD, Вы писали:

SLH>Как Вы посоветуете мне решать эту проблему — хранения вообще и медленного поиска в частности?


Мало данных для нормального ответа. Но нужно либо покрывать таблицы индексами либо попробовать использовать Indexed (materialized) views in Microsoft SQL Server
https://github.com/BlackEric001
Re: Как ускорить работу View (в MS SSQL)?
От: paucity  
Дата: 09.12.15 02:09
Оценка:
Здравствуйте, SteeLHeaD, Вы писали:

SLH>Есть бизнес — объект, называемый Order. Каждый его экземпляр хранится в строке таблицы Orders.

SLH>В нем около 150 полей, значительная часть (около половины) из которых — это id элементов справочников (перечислений).

Что-то слабо вериться, что Ордер может иметь 150 атрибутов. Походу, вы изначально запихали в Ордер то, что ему не принадлежит, отсюда последующие головняки.
Re: Как ускорить работу View (в MS SSQL)?
От: Sinclair Россия https://github.com/evilguest/
Дата: 31.03.16 11:20
Оценка: +1
Здравствуйте, SteeLHeaD, Вы писали:

SLH>Как Вы посоветуете мне решать эту проблему — хранения вообще и медленного поиска в частности?


Проблема хранения у вас решена корректно. Необязательные поля объявлены Null, повторяющиеся значения вынесены в справочники.
Проблему медленного поиска нужно решать путём профилирования и выпиливания узких мест.
Выпиливание узких мест = построение индексов. Для таблиц. Индексы для view (или материализованные view) — это очень специфическое средство, которое применимо не всегда.
Профилирование = просмотр планов запросов, которые вас не устраивают.
Ваше описание подходит под одну или несколько проблем:
1. В таблицах-справочниках нет индексов, которые позволяют быстро найти то, что нужно. Пример: во View есть ссылка из Order.CityID в таблицу City(ID, Name). Поиск делаем Where OrderView.CityName like 'Ново%' — получаем full scan таблицы городов. Решение: делаем индекс на city по (Name, Id), получаем index seek вместо full scan.
2. В основной таблице нет индексов, которые позволяют быстро найти то, что нужно. Пример: нет индекса, начинающегося с Order.СityID. Результат: Join у нас проходит в стиле inner loop. Решение: добавляем индекс пo (СityID, OrderID), запрос Where OrderView.CityName like 'Ново%' начинает летать.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.