|
|
|
Связанные списки
|
|||
|---|---|---|---|
|
#18+
Сначала упрощенная структура базы данных : Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. User может выбирать произвольные значения из списков A.Country и B.Journal после чего содержание списков обновляется с учетом сделанного выбора Так как списки связанные, значения выбранные в одном списке влияют на содержание другого списка Следовательно, чтобы обновить содержание списка с учетом выбора сделанного User-ом, необходимо включить в query все связанные таблицы, примерно так : Код: plaintext 1. 2. 3. 4. 5. и так для каждого списка меняя только выходное поле. Теперь - real life : таких связанных списков на клиенте больше 10-ти и они являются частью структуры более чем 30 связанных таблиц. Следовательно для обновления содержимого любого списка я каждый раз должен связывать эту огромную структуру таблиц, причем тело запроса абсолютно одинаковое для каждого списка, различается только выходное поле. В результате получаю ужасно медленный вывод содержимого связанных списков. Ну и собственно вопрос : что делать и кто виноват ? Regards, Snark ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.11.2002, 08:34:24 |
|
||
|
Связанные списки
|
|||
|---|---|---|---|
|
#18+
Сначала надо решить вопрос, что ты вообще делаешь. Связанные списки - точно не лучшее решение для SQL, который изначально не приспособлен оперировать понятиями "предыдущий" и "последующий". ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.11.2002, 16:48:59 |
|
||
|
Связанные списки
|
|||
|---|---|---|---|
|
#18+
Понятия "предыдущий" и "последующий" в этой задаче не присутствуют списки связаны не "вертикально" а "горизонтально" ... может быть точнее будет сказать не связанные а _синхронизированные_ списки .. то есть такие, где содержимое одного списка зависит от содержимого другого списка. По условиям задачи необходимо обновлять и синхронизировать содержимое каждого списка с учетом критериев поиска введенных пользователем. Например, в этом запросе, требуется вывести список уникальных названий журналов, из таблицы R, пользователя интересуют журналы с заголовками '1','2','3' причем Авторы ( [dbo].[A] ) Публикаций ( [dbo].[R] ) в этих журналах должы быть из стран 'A','B', 'C' Код: plaintext 1. 2. 3. 4. 5. получаем такой результат Journal -------------------------------------------------- 1 2 3 если же запрошены журналы с заголовками '1','2','3' причем Авторы ( [dbo].[A] ) Публикаций ( [dbo].[R] ) в этих журналах должы быть из стран 'A','B' Код: plaintext 1. 2. 3. 4. 5. то получаем такой результат Journal -------------------------------------------------- 1 2 то есть условия выборки из списка A.Country повлияли на содержимое списка R.Journal так же точно определенные условия выборки из списка R.Journal могут повлиять на содержимое списка A.Country Критерии поиска, заданные для каждого списка, взаимно влияют на обновленное содержание друг друга. Для того чтобы вывести обновленное содержимое каждого списка, каждый раз необходимо выполнять очень сложный запрос включающий несколько десятков INNER JOIN, так как в реальной базе данных, описанные списки являются частью структуры более чем 30 связанных таблиц Например этот запрос, который выводит список стран основываясь на тех же критериях выборки, что и предыдущий, Код: plaintext 1. 2. 3. 4. 5. почти идентичен предыдущему запросу за исключением поля вывода : SELECT DISTINCT dbo.A.Country Причем тело запроса - очень большое (так как в реальной задаче тело запроса состоит из нескольких десятков INNER JOIN) и отнимает львиную долю времени выполнения запроса. Напрашивается вопрос - нельзя ли как то reuse тело запроса, так чтобы запускать етот большой и сложный запрос один раз а потом использовать его результаты для быстрого обновления содержимого списков. Какие еще могут быть решения в этой ситуации ? Regards, Snark ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.11.2002, 20:52:31 |
|
||
|
Связанные списки
|
|||
|---|---|---|---|
|
#18+
может я чего то не допонял? View не пойдет? Код: plaintext 1. 2. 3. 4. 5. 6. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 09.11.2002, 14:06:54 |
|
||
|
Связанные списки
|
|||
|---|---|---|---|
|
#18+
Используешь ты View или нет тело запроса не меняется и соответственно не меняется время выполнения запроса. я как раз пытаюсь найти способ уменьшения времени выполнения запроса. Кстати я действительно в реальной задаче использую View но серверу все равно приходится JOIN эту кучу таблиц чтобы вывести список из 100 записей для каждого из 10 списков .. неэффективно. Вопрос собственно в масштабируемости данного подхода, когда требуется JOIN 2-5 таблиц для вывода одного списка это довольно эффективный запрос, когда же число таблиц больше 30 и приходится повторять почти идентичый запрос для вывода 10-20 списков это становится абсолютно неефективным, медленным подходом, да и выглядит как то не "нормально". Одним из подходов который я "изобрел" было сбрасывать содержимое View во временную таблицу, в рассчете на то что многочисленные JOIN будут производится только один раз а потом выборка значений списков будет происходить с помощью относительно быстрого запроса Код: plaintext 1. 2. 3. 4. работает неплохо для JOIN 5-10 - таблиц, но когда число таблиц увеличивается - размер временной таблицы растет в геометрической прогрессии, и время на создание этой таблицы становится просто неприемлемым, да и размер этой временной таблицы начинает измерятся гигабайтами. Другой подход очевиден - разбить многочисленные JOINs, на части которые логически не зависят друг от друга - количество JOIN уменьшится для создания каждого отдельного списка, так же как и время выполнения запроса. Ответ - независимых списков нет, выбор в каждом списке может повлиять на содержимое любого другого. Как то не верится что нет нормального решения этой ситуации, не я же один использую синхронизированные списки. Regards, Snark ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 09.11.2002, 21:11:24 |
|
||
|
Связанные списки
|
|||
|---|---|---|---|
|
#18+
если серв 2к сторой индексированное представление.... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 09.11.2002, 21:52:16 |
|
||
|
Связанные списки
|
|||
|---|---|---|---|
|
#18+
Indexed views не позволяют использование LEFT OUTER JOIN которые присутствуют в реальном запросе ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.11.2002, 08:26:45 |
|
||
|
Связанные списки
|
|||
|---|---|---|---|
|
#18+
а ты попробуй условие выборки запихнуть в join а не в where - по логики должно на много сократить время выборки ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.11.2002, 10:15:33 |
|
||
|
Связанные списки
|
|||
|---|---|---|---|
|
#18+
Нельзя ли привести примерчик как в моем случае условие выборки запихнуть в join ? Все условия выборки в моем случае это where .. in(1,2,3..n) Regards, Snark ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.11.2002, 20:11:08 |
|
||
|
Связанные списки
|
|||
|---|---|---|---|
|
#18+
строй индексированные вью без outer... а запрос можно переделать..... все равно быстрее будет.... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.11.2002, 21:09:28 |
|
||
|
Связанные списки
|
|||
|---|---|---|---|
|
#18+
To MiCe : Пробовал, создал индексированное представление - ViewIN, содержащее только INNER JOIN и включил его в другое представление - ViewOUT, где содержатся LEFT OUTER JOIN. Также для запроса ViewIN, кроме кластерного индекса, создал индексы для всеx полей по которым может происходить JOIN а также для всех полей по которым может идти поиск. Запрос для заполнение списка журналов, с использованием индексированного представления : Код: plaintext 1. 2. работает на 8% быстрее чем такой же запрос с использованием неиндексированного представления. Причем под индексы для индексированного представления ViewIN зарезервированно 1408 KB, тогда как неиндексированное представление, как известно, места не занимает. Также проверял производительность непосредственно для индексированной и неиндексированной версии представления ViewIN - разницы вообще нет, или она статистически недостоверна, колеблется на доли процента в обе стороны. Игра не стоит свеч. Regards, Snark ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.11.2002, 01:56:43 |
|
||
|
Связанные списки
|
|||
|---|---|---|---|
|
#18+
ViewOUT не нужно.... строй идксы которых нет в исходных таблицах... OUTER join можно вообще не использовать... игра вообще нестоит свеч если операций вставки столькоже сколько и чтений..... по оптимизации... избегай по возможности IN... меняй на EXISTS... ограничивай наборы до объединения... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.11.2002, 09:38:33 |
|
||
|
Связанные списки
|
|||
|---|---|---|---|
|
#18+
Согласен с MiCe замени in на exist ы или несколько = ; А вот пример с join Код: plaintext 1. 2. 3. 4. 5. Like привел для примера - на самом деле тоже медленно работает, лучьше используй = ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.11.2002, 10:17:23 |
|
||
|
Связанные списки
|
|||
|---|---|---|---|
|
#18+
ViewOUT не нужно.... - понимаю что ViewOUT не обязателен, но на производительность не влияет строй идксы которых нет в исходных таблицах... - это хорошее замечание помогло сократить размер ViewIN в несколько раз, спасибо OUTER join можно вообще не использовать... - тут я не понял, как без OUTER JOIN ? .. например зачем LEFT OUTER JOIN используется в моей задаче : кроме описанных выше таблиц, есть таблица Reference_User Код: plaintext 1. дело в том что некоторые Публикации - конфиденциальны и могут показываться только определенным Пользователям, поэтому создана такая таблица где хранится информация о таких комбинациях : Конфиденциальной публикации и Пользователя который ее может видеть поэтому запрос для заполнения списка журналов на самом деле выглядит так : Код: plaintext 1. 2. 3. 4. 5. 6. 7. будут показаны журналы только с названиями "1", "2" или "3" где авторы публикаций в этих журналах из стран "А" или "B", причем будут показаны только конфиденциальные публикации разрешенные для просмотра Пользователю 123 И все публикации которые находятся в свободном доступе. Как в данном случае обойтись без LEFT OUTER JOIN ? игра вообще нестоит свеч если операций вставки столькоже сколько и чтений..... - В данной задаче операции чтения гораздо чаще чем операции INSERT и UPDATE, хотя интересно не может ли блокировать созданный кластерный индекс ViewIN операции INSERT и UPDATE ? по оптимизации... избегай по возможности IN... меняй на EXISTS... опять не понимаю как в данном случае можно заменить IN на EXISTS ? Все критерии выборки приходят с клиента, пользователь может выбирать произвольные значения из любого синxронизированного списка, предсказать какие значения прийдут с клиента невозможно. ограничивай наборы до объединения... это я понимаю, и имею в виду, но не вижу возможностей ограничения кстати, включение опции WITH (NOEXPAND) действительно заставило индексированное представление ViewIN работать значительно (примерно в 10 раз) быстрее, но после наложения всех критериев выборки, план выполнения запроса опять сбивается и в итоге скорость выполнения запроса с использованием индексированного представления становится такой же как и с использованием такого же неиндексированного представления Regards, Snark ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.11.2002, 11:03:20 |
|
||
|
Связанные списки
|
|||
|---|---|---|---|
|
#18+
в данном случае поможет OR.... (dbo.A.Country IN ('A', 'B')) ->(dbo.A.Country = 'A' OR dbo.A.Country = 'B')....(посмотри план... может вынести вообще в from / FROM dbo.A ->FROM (select * from dbo.A where dbo.A.Country = 'A' OR dbo.A.Country = 'B') as a / ) кароче.... ;)) вот.... Код: plaintext 1. 2. 3. 4. 5. 6. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.11.2002, 11:41:03 |
|
||
|
Связанные списки
|
|||
|---|---|---|---|
|
#18+
скорость думаю на порядок вырастет... ;)) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.11.2002, 11:52:07 |
|
||
|
Связанные списки
|
|||
|---|---|---|---|
|
#18+
виноват... Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. ne dbo.Reference_User.ReferenceID = 133 a dbo.Reference_User.UserID =133 Snark ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.11.2002, 12:02:22 |
|
||
|
Связанные списки
|
|||
|---|---|---|---|
|
#18+
если делать так как вы с дао предложили: Код: plaintext 1. 2. то про индексированное представление можно забыть, дело в том что критерии выборки это динамическая часть запроса, не могу же я создавать новый индексированное представление каждый раз когда пользователь поменял критерии выборки - я честно говоря не понимаю смысла этой замены, (dbo.A.Country IN ('A', 'B')) ->(dbo.A.Country = 'A' OR dbo.A.Country = 'B').... тем более что сервер, судя по плану выполнения запроса, сам делает это преобразование, а я изпользую WHERE IN просто потому что ето более компактный способ передачи критерия выборки на сервер ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.11.2002, 12:22:48 |
|
||
|
Связанные списки
|
|||
|---|---|---|---|
|
#18+
А смысл в том что where -накладывается после обьединения а предложенные нами варианты до.Следовательно в обьединение участвует намного меньше записей. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.11.2002, 16:02:57 |
|
||
|
Связанные списки
|
|||
|---|---|---|---|
|
#18+
строим индексированные представления для двух целей... получить дополнительные индексы при сложном объединении и получать просчитанные результаты.... ограничиваем выборки до объединения.... в остальном сервер сам разбирется... и индексы будет использовать и результаты... оптимизатор у мелкомягких один из самых лучших... но он тоже не гений... ;))) если ему помогать - хорошая спака получается.... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.11.2002, 18:10:27 |
|
||
|
|

start [/forum/topic.php?fid=46&fpage=3378&tid=1818869]: |
0ms |
get settings: |
5ms |
get forum list: |
9ms |
check forum access: |
2ms |
check topic access: |
2ms |
track hit: |
32ms |
get topic data: |
6ms |
get forum data: |
2ms |
get page messages: |
68ms |
get tp. blocked users: |
1ms |
| others: | 193ms |
| total: | 320ms |

| 0 / 0 |
