Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Связанные списки / 21 сообщений из 21, страница 1 из 1
08.11.2002, 08:34:24
    #32065804
Snark
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Связанные списки
Сначала упрощенная структура базы данных :
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
CREATE TABLE [dbo].[A] ([AID] [int] NOT NULL ,[Name] [varchar] ( 50 ),[Country] [varchar] ( 50 )) ON [PRIMARY]
CREATE TABLE [dbo].[R]([RID] [int] NOT NULL ,[Title] [varchar] ( 50 ),[Journal] [varchar] ( 50 )) ON [PRIMARY]
CREATE TABLE [dbo].[R_A] ([AID] [int] NOT NULL ,[RID] [int] NOT NULL) ON [PRIMARY]
ALTER TABLE [dbo].[A] ADD CONSTRAINT [PK_A] PRIMARY KEY  CLUSTERED ([AID])  ON [PRIMARY] 
ALTER TABLE [dbo].[R] ADD CONSTRAINT [PK_R] PRIMARY KEY  CLUSTERED ([RID])  ON [PRIMARY] 
ALTER TABLE [dbo].[R_A] WITH NOCHECK ADD CONSTRAINT [PK_R_A] PRIMARY KEY  CLUSTERED([AID],[RID])  ON [PRIMARY] 
ALTER TABLE [dbo].[R_A] ADD CONSTRAINT [FK_R_A_A] FOREIGN KEY ([AID]) REFERENCES [dbo].[A]([AID]),
			    CONSTRAINT [FK_R_A_R] FOREIGN KEY ([RID]) REFERENCES [dbo].[R] ([RID])			    
			    
INSERT A VALUES ( 1 , 'A', 'A')
INSERT A VALUES ( 2 , 'B', 'B')
INSERT A VALUES ( 3 , 'C', 'C')
INSERT R VALUES ( 1 , '1', '1')
INSERT R VALUES ( 2 , '2', '2')
INSERT R VALUES ( 3 , '3', '3')
INSERT R_A VALUES ( 1 ,  1 )
INSERT R_A VALUES ( 1 ,  2 )
INSERT R_A VALUES ( 2 ,  1 )
INSERT R_A VALUES ( 2 ,  3 )
INSERT R_A VALUES ( 3 ,  3 )

User может выбирать произвольные значения из списков A.Country и B.Journal
после чего содержание списков обновляется с учетом сделанного выбора
Так как списки связанные, значения выбранные в одном списке влияют на содержание другого списка
Следовательно, чтобы обновить содержание списка с учетом выбора сделанного User-ом, необходимо
включить в query все связанные таблицы, примерно так :
Код: plaintext
1.
2.
3.
4.
5.
SELECT DISTINCT A.Country
FROM  A INNER JOIN
               R_A ON A.AID = R_A.AID INNER JOIN
               R ON R_A.RID = R.RID
WHERE (A.Country IN ('A', 'B')) AND (R.Journal IN ('1', '2', '3'))

и так для каждого списка меняя только выходное поле.

Теперь - real life :
таких связанных списков на клиенте больше 10-ти и они являются частью структуры
более чем 30 связанных таблиц.
Следовательно для обновления содержимого любого списка я каждый раз должен
связывать эту огромную структуру таблиц,
причем тело запроса абсолютно одинаковое для каждого списка, различается только выходное поле.
В результате получаю ужасно медленный вывод содержимого связанных списков.
Ну и собственно вопрос : что делать и кто виноват ?

Regards, Snark
...
Рейтинг: 0 / 0
08.11.2002, 16:48:59
    #32065882
Gobzo Kobler
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Связанные списки
Сначала надо решить вопрос, что ты вообще делаешь. Связанные списки - точно не лучшее решение для SQL, который изначально не приспособлен оперировать понятиями "предыдущий" и "последующий".
...
Рейтинг: 0 / 0
08.11.2002, 20:52:31
    #32065911
Snark
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Связанные списки
Понятия "предыдущий" и "последующий" в этой задаче не присутствуют списки связаны
не "вертикально" а "горизонтально" ... может быть точнее будет сказать
не связанные а _синхронизированные_ списки ..
то есть такие, где содержимое одного списка зависит от содержимого другого списка.
По условиям задачи необходимо обновлять и синхронизировать содержимое каждого
списка с учетом критериев поиска введенных пользователем.
Например, в этом запросе, требуется вывести список уникальных названий журналов,
из таблицы R,
пользователя интересуют журналы с заголовками '1','2','3'
причем Авторы ( [dbo].[A] ) Публикаций ( [dbo].[R] ) в этих журналах должы быть из стран 'A','B', 'C'
Код: plaintext
1.
2.
3.
4.
5.
SELECT DISTINCT dbo.R.Journal
FROM  dbo.A INNER JOIN
               dbo.R_A ON dbo.A.AID = dbo.R_A.AID INNER JOIN
               dbo.R ON dbo.R_A.RID = dbo.R.RID
WHERE (dbo.A.Country IN ('A', 'B', 'C') AND dbo.R.Journal IN ('1', '2', '3'))               


получаем такой результат

Journal
--------------------------------------------------
1
2
3

если же запрошены журналы с заголовками '1','2','3' причем Авторы ( [dbo].[A] ) Публикаций ( [dbo].[R] )
в этих журналах должы быть из стран 'A','B'
Код: plaintext
1.
2.
3.
4.
5.
SELECT DISTINCT dbo.R.Journal
FROM  dbo.A INNER JOIN
               dbo.R_A ON dbo.A.AID = dbo.R_A.AID INNER JOIN
               dbo.R ON dbo.R_A.RID = dbo.R.RID
WHERE (dbo.A.Country IN ('A', 'B')) AND (dbo.R.Journal IN ('1', '2', '3'))

то получаем такой результат

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
FROM  dbo.A INNER JOIN
               dbo.R_A ON dbo.A.AID = dbo.R_A.AID INNER JOIN
               dbo.R ON dbo.R_A.RID = dbo.R.RID
WHERE (dbo.A.Country IN ('A', 'B')) AND (dbo.R.Journal IN ('1', '2', '3'))

почти идентичен предыдущему запросу за исключением поля вывода : SELECT DISTINCT dbo.A.Country
Причем тело запроса - очень большое
(так как в реальной задаче тело запроса состоит из нескольких десятков INNER JOIN)
и отнимает львиную долю времени выполнения запроса.
Напрашивается вопрос - нельзя ли как то reuse тело запроса,
так чтобы запускать етот большой и сложный запрос один раз а потом использовать его
результаты для быстрого обновления содержимого списков.
Какие еще могут быть решения в этой ситуации ?

Regards, Snark
...
Рейтинг: 0 / 0
09.11.2002, 14:06:54
    #32065946
MiCe
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Связанные списки
может я чего то не допонял?
View не пойдет?
Код: plaintext
1.
2.
3.
4.
5.
6.
CREATE VIEW vw_r_a
AS
SELECT A.AID, A.[Name] ,A.[Country],
           R.RID, R.[Title], R.[Journal] 
FROM  A INNER JOIN
               R_A ON A.AID = R_A.AID INNER JOIN
               R ON R_A.RID = R.RID
...
Рейтинг: 0 / 0
09.11.2002, 21:11:24
    #32065959
Snark
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Связанные списки
Используешь ты View или нет тело запроса не меняется и
соответственно не меняется время выполнения запроса.
я как раз пытаюсь найти способ уменьшения времени выполнения запроса.
Кстати я действительно в реальной задаче использую View но
серверу все равно приходится JOIN эту кучу таблиц чтобы
вывести список из 100 записей для каждого из 10 списков .. неэффективно.
Вопрос собственно в масштабируемости данного подхода, когда требуется
JOIN 2-5 таблиц для вывода одного списка это довольно эффективный запрос,
когда же число таблиц больше 30 и приходится повторять почти идентичый запрос
для вывода 10-20 списков это становится абсолютно неефективным, медленным подходом,
да и выглядит как то не "нормально".
Одним из подходов который я "изобрел" было сбрасывать содержимое View
во временную таблицу, в рассчете на то что многочисленные JOIN будут
производится только один раз а потом выборка значений списков будет происходить
с помощью относительно быстрого запроса
Код: plaintext
1.
2.
3.
4.
  
SELECT DISTINCT Country FROM #MyTable
SELECT DISTINCT Journal FROM #MyTable
etc.

работает неплохо для JOIN 5-10 - таблиц, но когда число таблиц увеличивается -
размер временной таблицы растет в геометрической прогрессии,
и время на создание этой таблицы становится просто неприемлемым,
да и размер этой временной таблицы начинает измерятся гигабайтами.
Другой подход очевиден - разбить многочисленные JOINs,
на части которые логически не зависят друг от друга - количество JOIN
уменьшится для создания каждого отдельного списка,
так же как и время выполнения запроса.
Ответ - независимых списков нет, выбор в каждом списке может повлиять на
содержимое любого другого.
Как то не верится что нет нормального решения этой ситуации,
не я же один использую синхронизированные списки.

Regards, Snark
...
Рейтинг: 0 / 0
09.11.2002, 21:52:16
    #32065961
MiCe
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Связанные списки
если серв 2к сторой индексированное представление....
...
Рейтинг: 0 / 0
10.11.2002, 08:26:45
    #32065980
Snark
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Связанные списки
Indexed views не позволяют использование LEFT OUTER JOIN которые присутствуют в реальном запросе
...
Рейтинг: 0 / 0
10.11.2002, 10:15:33
    #32065999
dao
dao
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Связанные списки
а ты попробуй условие выборки запихнуть в join а не в where - по логики должно на много сократить время выборки
...
Рейтинг: 0 / 0
10.11.2002, 20:11:08
    #32066225
Snark
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Связанные списки
Нельзя ли привести примерчик как в моем случае условие выборки запихнуть в join ? Все условия выборки в моем случае это where .. in(1,2,3..n)
Regards, Snark
...
Рейтинг: 0 / 0
10.11.2002, 21:09:28
    #32066233
MiCe
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Связанные списки
строй индексированные вью без outer...
а запрос можно переделать..... все равно быстрее будет....
...
Рейтинг: 0 / 0
11.11.2002, 01:56:43
    #32066248
Snark
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Связанные списки
To MiCe :
Пробовал, создал индексированное представление - ViewIN, содержащее только INNER JOIN и
включил его в другое представление - ViewOUT, где содержатся LEFT OUTER JOIN.
Также для запроса ViewIN, кроме кластерного индекса, создал индексы для всеx полей
по которым может происходить JOIN а также для всех полей по которым может идти поиск.
Запрос для заполнение списка журналов, с использованием индексированного представления :
Код: plaintext
1.
2.
   Select DISTINCT Journal from ViewOUT where 
    WHERE (Country IN ('A', 'B')) AND (Journal IN ('1', '2', '3'))
  

работает на 8% быстрее чем такой же запрос с использованием неиндексированного представления.
Причем под индексы для индексированного представления ViewIN зарезервированно 1408 KB,
тогда как неиндексированное представление, как известно, места не занимает.
Также проверял производительность непосредственно для индексированной и неиндексированной
версии представления ViewIN - разницы вообще нет, или она статистически недостоверна, колеблется
на доли процента в обе стороны.
Игра не стоит свеч.

Regards, Snark
...
Рейтинг: 0 / 0
11.11.2002, 09:38:33
    #32066301
MiCe
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Связанные списки
ViewOUT не нужно....
строй идксы которых нет в исходных таблицах...
OUTER join можно вообще не использовать...
игра вообще нестоит свеч если операций вставки столькоже сколько и чтений.....
по оптимизации... избегай по возможности IN...
меняй на EXISTS... ограничивай наборы до объединения...
...
Рейтинг: 0 / 0
11.11.2002, 10:17:23
    #32066326
dao
dao
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Связанные списки
Согласен с MiCe замени in на exist ы или несколько = ; А вот пример с join
Код: plaintext
1.
2.
3.
4.
5.
FROM  A INNER JOIN

               R_A ON A.AID = R_A.AID  and (A.Country= 'A' or  A.Country='B') INNER JOIN

               R ON R_A.RID = R.RID AND (R.Journal  like ([ 1 - 3 ])

Like привел для примера - на самом деле тоже медленно работает, лучьше используй =
...
Рейтинг: 0 / 0
11.11.2002, 11:03:20
    #32066353
Snark
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Связанные списки
ViewOUT не нужно....
- понимаю что ViewOUT не обязателен, но на производительность не влияет
строй идксы которых нет в исходных таблицах...
- это хорошее замечание помогло сократить размер ViewIN в несколько раз, спасибо
OUTER join можно вообще не использовать...
- тут я не понял, как без OUTER JOIN ? ..
например зачем LEFT OUTER JOIN используется в моей задаче :
кроме описанных выше таблиц, есть таблица Reference_User
Код: plaintext
1.
CREATE TABLE [dbo].[Reference_User]([ReferenceID] [int] NOT NULL, [UserID] [int] NOT NULL) ON [PRIMARY]

дело в том что некоторые Публикации - конфиденциальны и могут показываться только определенным Пользователям,
поэтому создана такая таблица где хранится информация о таких комбинациях :
Конфиденциальной публикации и Пользователя который ее может видеть
поэтому запрос для заполнения списка журналов на самом деле выглядит так :
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
SELECT DISTINCT dbo.R.Journal
FROM         dbo.A INNER JOIN
                      dbo.R_A ON dbo.A.AID = dbo.R_A.AID INNER JOIN
                      dbo.R ON dbo.R_A.RID = dbo.R.RID LEFT OUTER JOIN
                      dbo.Reference_User ON dbo.R.RID = dbo.Reference_User.ReferenceID
WHERE     (dbo.A.Country IN ('A', 'B')) AND (dbo.R.Journal IN ('1', '2', '3')) AND 
          (dbo.Reference_User.ReferenceID =  133  OR dbo.Reference_User.ReferenceID IS NULL))) 

будут показаны журналы только с названиями "1", "2" или "3" где авторы публикаций в этих
журналах из стран "А" или "B", причем будут показаны только конфиденциальные публикации
разрешенные для просмотра Пользователю 123 И все публикации которые находятся в свободном
доступе. Как в данном случае обойтись без LEFT OUTER JOIN ?

игра вообще нестоит свеч если операций вставки столькоже сколько и чтений.....
- В данной задаче операции чтения гораздо чаще чем операции INSERT и UPDATE,
хотя интересно не может ли блокировать созданный кластерный индекс ViewIN операции INSERT и UPDATE ?
по оптимизации...
избегай по возможности IN... меняй на EXISTS...

опять не понимаю как в данном случае можно заменить IN на EXISTS ?
Все критерии выборки приходят с клиента, пользователь может выбирать произвольные
значения из любого синxронизированного списка, предсказать какие значения прийдут с
клиента невозможно.
ограничивай наборы до объединения...
это я понимаю, и имею в виду, но не вижу возможностей ограничения

кстати, включение опции WITH (NOEXPAND) действительно заставило индексированное
представление ViewIN работать значительно (примерно в 10 раз) быстрее,
но после наложения всех критериев выборки, план выполнения запроса опять сбивается
и в итоге скорость выполнения запроса с использованием индексированного представления
становится такой же как и с использованием такого же неиндексированного представления

Regards, Snark
...
Рейтинг: 0 / 0
11.11.2002, 11:41:03
    #32066373
MiCe
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Связанные списки
в данном случае поможет 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.
SELECT DISTINCT dbo.R.Journal
FROM  (select AID from dbo.A where Country='A' OR Country='B') a INNER JOIN
                      dbo.R_A ra ON a.AID = ra.AID INNER JOIN
      (select RID,Journal from dbo.R where Journal='1' OR Journal='2' OR Journal='3') r ON ra.RID = r.RID 
WHERE  r.RID= 133  OR 
NOT EXISTS (SELCT top  1  * from dbo.Reference_User ru where ru.ReferenceID=r.RID ) 
...
Рейтинг: 0 / 0
11.11.2002, 11:52:07
    #32066379
MiCe
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Связанные списки
скорость думаю на порядок вырастет... ;))
...
Рейтинг: 0 / 0
11.11.2002, 12:02:22
    #32066386
Snark
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Связанные списки
виноват...
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
 
 SELECT DISTINCT dbo.R.Journal
FROM         dbo.A INNER JOIN
                      dbo.R_A ON dbo.A.AID = dbo.R_A.AID INNER JOIN
                      dbo.R ON dbo.R_A.RID = dbo.R.RID LEFT OUTER JOIN
                      dbo.Reference_User ON dbo.R.RID = dbo.Reference_User.ReferenceID
WHERE (dbo.A.Country IN ('A', 'B')) AND (dbo.R.Journal IN ('1', '2', '3')) AND     
(dbo.Reference_User.UserID =  133 ) OR (dbo.Reference_User.UserID IS NULL)

ne
dbo.Reference_User.ReferenceID = 133
a
dbo.Reference_User.UserID =133

Snark
...
Рейтинг: 0 / 0
11.11.2002, 12:22:48
    #32066393
Snark
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Связанные списки
если делать так как вы с дао предложили:
Код: plaintext
1.
2.
SELECT DISTINCT dbo.R.Journal
FROM  (select AID from dbo.A where Country='A' OR Country='B') a INNER JOIN

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

- я честно говоря не понимаю смысла этой замены,
(dbo.A.Country IN ('A', 'B')) ->(dbo.A.Country = 'A' OR dbo.A.Country = 'B')....
тем более что сервер, судя по плану выполнения запроса, сам делает это преобразование,
а я изпользую WHERE IN просто потому что ето более компактный способ передачи критерия
выборки на сервер
...
Рейтинг: 0 / 0
11.11.2002, 16:02:57
    #32066553
dao
dao
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Связанные списки
А смысл в том что where -накладывается после обьединения а предложенные нами варианты до.Следовательно в обьединение участвует намного меньше записей.
...
Рейтинг: 0 / 0
11.11.2002, 18:10:27
    #32066635
MiCe
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Связанные списки
строим индексированные представления для двух целей...
получить дополнительные индексы при сложном объединении и получать просчитанные результаты....
ограничиваем выборки до объединения....
в остальном сервер сам разбирется... и индексы будет использовать и результаты...
оптимизатор у мелкомягких один из самых лучших... но он тоже не гений... ;))) если ему помогать - хорошая спака получается....
...
Рейтинг: 0 / 0
12.11.2002, 20:09:43
    #32067175
Snark
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Связанные списки
Спасибо за очень интересное обсуждение
Regards, Snark
...
Рейтинг: 0 / 0
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Связанные списки / 21 сообщений из 21, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]