Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Индексы и UNION / 18 сообщений из 18, страница 1 из 1
05.08.2002, 15:05:13
    #32040918
Roman M
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Индексы и UNION
Если я объединяю в представлении данные из двух проиндексированных таблиц (UNION), а потом в конструкции where ... использую это представление, то наблюдается тормоз...
Индексы не работают?
Как этого избежать?
...
Рейтинг: 0 / 0
05.08.2002, 15:21:38
    #32040922
VVG_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Индексы и UNION
Саму вьюху проиндексировать не получится. union для indexed view запрещен.

Можно перед обработкой всю вьюху сливать во временную таблицу и индексировать ее.

Можно сделать отдельную табличку с полями, общими для двух таблиц на которые повесить нужные триггера.
...
Рейтинг: 0 / 0
05.08.2002, 15:56:02
    #32040932
Garya
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Индексы и UNION
Если в двух таблицах нет и не может быть схожих записей, то вместо UNION необходимо использовать UNION ALL. При таком объединении не будет попарно производиться сравнение всех записей из этих таблиц для выявления повторяющихся записей (изкоторых пир использовании UNION необходимо включить в результирующий набор только одну копию). И работать все будет гораздо быстрее.
...
Рейтинг: 0 / 0
05.08.2002, 16:55:14
    #32040946
MiCe
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Индексы и UNION
согласен с Garya...
на таком принципе обычно стороятся хранилища.....
...
Рейтинг: 0 / 0
05.08.2002, 17:48:27
    #32040972
Roman M
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Индексы и UNION
Спасибо, Garya, последовал Вашему совету, но, к сожалению, быстродействие не увеличилось.
...
Рейтинг: 0 / 0
05.08.2002, 17:53:57
    #32040976
MiCe
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Индексы и UNION
покажите структуру с индексами и текст вью...
...
Рейтинг: 0 / 0
06.08.2002, 11:07:51
    #32041109
Roman M
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Индексы и UNION
Ух, не знаю, захочет ли кто-нибудь прочитать столько кода, но все-таки:

Текст вьюхи с UNION: Prihod

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
SELECT Money.Autonumber AS ID, Date, Summa, Currency, 
    DSumma, CurrencyFact, Payer
FROM Money
UNION ALL
SELECT Waybill.IDWaybill, Date, Summa, Currency,  0 ,  1 , 
    Seller
FROM Waybill
WHERE Waybill.Shipment =  1 
UNION ALL
SELECT Markdown.IDMarkdown, MarkDown.Date, 
    MarkDown.MarkDownSumma, Waybill.Currency,  0 ,  1 , 
    Waybill.Seller
FROM MarkDown INNER JOIN
    WaybillDetail ON 
    Markdown.WD = WaybillDetail.IDWD INNER JOIN
    Waybill ON WaybillDetail.IDWaybill = Waybill.IDWaybill


Текст второй вьюхи с UNION: Rashod

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
SELECT IDWaybill, Waybill, Date, Consignee, Summa, Currency, 
    DSumma =  0 , CurrencyFact =  0 
FROM Waybill
WHERE Waybill.Shipment =  1 
UNION ALL
SELECT Autonumber, NumDoc, Date, Receiver, Summa, Currency, 
    DSumma, CurrencyFact
FROM Money


А вот кусок текста триггера, в котором используются предыдущие вьюхи:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
begin
Update Waybill
set PaymentDate = (select min(Prihod.Date) from Prihod
	Where 
	 -- Сумма расходов до текущей накладной
 
	isnull((select sum(Rashod.Summa) 
	from Rashod Where Rashod.Date<Inserted.Date and 
	Rashod.Currency =  1  and Rashod.Consignee = Inserted.Consignee), 0 )+	
	 -- Сумма расходов в день отгрузки текущей накладной
 
	isnull((select sum(Rashod.Summa) 
	from Rashod Where Rashod.Date=Inserted.Date and Rashod.IDWaybill<=Inserted.IDWaybill and 
	Rashod.Currency =  1  and Rashod.Consignee = Inserted.Consignee), 0 )+

	isnull((select sum(Rashod.DSumma) 
	from Rashod Where Rashod.Date<Inserted.Date and 
	Rashod.CurrencyFact =  1  and Rashod.Consignee = Inserted.Consignee), 0 )+	
	isnull((select sum(Rashod.DSumma) 
	from Rashod Where Rashod.Date=Inserted.Date and Rashod.IDWaybill<=Inserted.IDWaybill and 
	Rashod.CurrencyFact =  1  and Rashod.Consignee = Inserted.Consignee), 0 )
<=
	 -- Сумма приходов (деньги + накладные + уценки)
 
	isnull((select sum(P.Summa) from Prihod P
	Where P.Date<= Prihod.Date and 
	P.Payer = Inserted.Consignee and P.Currency= 1 ), 0 )+
	isnull((select sum(P.DSumma) from Prihod P
	Where P.Date<= Prihod.Date and 
	P.Payer = Inserted.Consignee and P.CurrencyFact= 1 ), 0 )

and Prihod.Payer = Inserted.Consignee  and Inserted.Currency =  1 
)
from Waybill inner join Inserted on
Waybill.IDWaybill = Inserted.IDWaybill
end


Все таблицы проиндексированы по полям, присутствующим в Where триггера
Так вот, триггер обрабатывает одну запись ~ 2 секунды! Это сильно портит жизнь.
...
Рейтинг: 0 / 0
06.08.2002, 12:01:15
    #32041146
Garya
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Индексы и UNION
> Все таблицы проиндексированы по полям, присутствующим в Where триггера...

Присутствовать-то они там присутствуют, да только внутри вычисляемого выражения IsNul(...). А это приводит к неиспользованию индексов и полному сканированию таблицы. А если учесть еще и такое количество подзапросов с агрегатными функциями, то можно удивляться, что ты вообще можешь дождаться, когда все это отработает.
Нужно кардинально все это хозяйство переделывать. Нужно кумекать. Как вариант, завести вспомогательную таблицу для итогов/подитогов и триггерами на модификацию этих самых приходов/расходов туда прибавалять итоги. Механиз транзакций гарантирует целостность и соответствие содержимого этой таблицы содержимому таблиц приходов/расходов. Избавишься от агрегатных функций.
А для начала просто вызови VIEW из QA и засеки время - сколько он открывается. IMHO, проблема не во VIEW, а в триггере.
P.S. Если в триггере используются к тому же временные таблицы (либо табличные переменные), то триггер компилируется при каждом вызове, на что уходит дополнительное время.
...
Рейтинг: 0 / 0
06.08.2002, 15:18:40
    #32041252
Roman M
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Индексы и UNION
2 Garya:
Убрал IsNull(), время обработки не уменьшилось.

View открывается 16 секунд. 43000 строк.
Не знаю, много это или мало
...
Рейтинг: 0 / 0
06.08.2002, 15:38:10
    #32041260
MiCe
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Индексы и UNION
а что показывает план запроса на вьюхах?
...
Рейтинг: 0 / 0
06.08.2002, 15:46:02
    #32041265
Зайцев Фёдор
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Индексы и UNION
Правильно не изменилось.
IsNull как раз почти не тормозит. Я бы сказал "совсем не тормозит", но не было случая проверить ВСЕ варианты.
...
Рейтинг: 0 / 0
06.08.2002, 16:17:01
    #32041279
Roman M
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Индексы и UNION
2 MiCe:

Слева - направо, сверху - вниз

Select Cost: 0%
Concatenation 0%
Compute Scalar 0%
Table Scan 32%
Filter 1%
Table scan 12%
Bookmark Lookup 9%
Nested Loops/Inner join 0%
Bookmark Lookup 38%
Nested Loops/Inner join 0%
Table Scan 4%
WaybillDetail... Что-то там про Index seek 2%
Waybill... Index seek 1%
...
Рейтинг: 0 / 0
06.08.2002, 16:31:55
    #32041284
MiCe
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Индексы и UNION
помоему при таком количестве он вьхи засовывает в темптабл....
ща еще подемаю...
...
Рейтинг: 0 / 0
06.08.2002, 17:33:59
    #32041300
Garya
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Индексы и UNION
У тебя слишком много агрегатных функций, каждая из которых вычисляется отдельным сканированием. Попробуй уменьшить количество подзапросов и/или агрегатных функций. Мне, в частности, не понятно, зачем в первом подзапросе нужно вычислять приходы ДО текущей дате (по условию <), а во втором отдельно приходы по текущей дате (по условию =). Нельзя их как-нибудь объединить в один подзапрос по условию <=?
А вот если приходы и расходы хранить вообще в одной таблице, то вместо всей груды подзапросов достаточно вообще одного, у которого внутри summ() находится case, который приходы суммирует с плюсом, а расходы - с минусом.
Если этот вариант не нравится, обрати внимание на еще одно решение, предложенное в моем предыдущем постинге (с триггерами, отслеживающими итоговые данные).
...
Рейтинг: 0 / 0
06.08.2002, 18:00:17
    #32041305
Roman M
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Индексы и UNION
2 Garya:

>Мне, в частности, не понятно, зачем в первом подзапросе нужно вычислять приходы ДО текущей дате (по условию <), а во втором отдельно приходы по текущей дате (по условию =). Нельзя их как-нибудь объединить в один подзапрос по условию <=?

К сожалению, нельзя. В поле Date хранится только дата, без времени, записей с одинаковой датой может быть несколько, а нужно как-то выбирать записи до текущей.
Вот и пришлось извратиться, используя 2 подзапроса:
в первом выбираются записи с датой меньше текущей, а во втором - записи с датой, соответствующей текущей, но с ID, меньшим либо равным, чем у текущей записи.

Приходы и расходы хранить в одной таблице вообще нельзя:
Приходами у меня считаются поступления денег, поступления товара (входящие накладные), уценки. Это естественно все разные таблицы.
Расходы - деньги, товар (исходящие накладные).

Входящие и исходящие накладные лежат в одной таблице, Входящие и исходящие деньги - тоже в одной таблице.

Пихать накладные и деньги в одну таблицу - я думаю не стоит.

>Как вариант, завести вспомогательную таблицу для итогов/подитогов и триггерами на модификацию этих самых приходов/расходов туда прибавалять итоги.

Так это я и делаю! В таблице Waybill (Накладные) я в поле PaymentDate сохраняю дату оплаты накладной.
...
Рейтинг: 0 / 0
06.08.2002, 18:22:36
    #32041312
Garya
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Индексы и UNION
> ...в первом выбираются записи с датой меньше текущей, а во втором - записи с датой, соответствующей текущей, но с ID, меньшим либо равным, чем у текущей записи...

Так, может, дата воббще не нужна!? Достаточно одного ID?

> Так это я и делаю! В таблице Waybill (Накладные) я в поле PaymentDate сохраняю дату оплаты накладной

Я не про дату, а про сумму. Для того чтобы не писать select sum(Prohod.Summa) form Prihod, можно завести вспомогательную таблицу, в которой триггерами на Insert/update/delete, прицепленными к таблице Prihod , получать эту самую сумму. А в том скрипте, который изображен, использовать простой select SumFld from AddTable where ...
...
Рейтинг: 0 / 0
07.08.2002, 10:59:42
    #32041416
Roman M
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Индексы и UNION
2 Garya:

>Так, может, дата воббще не нужна!? Достаточно одного ID?

К сожалению, нужна. Ведь не обязательно у накладной с меньшей датой меньший ID. Юзер может создать накладную на послезавтра (ID=1), а потом на завтра(ID=2).
Специфика задачи.

>Я не про дату, а про сумму. Для того чтобы не писать select sum(Prohod.Summa) form Prihod, можно завести вспомогательную таблицу, в которой триггерами на Insert/update/delete, прицепленными к таблице Prihod, получать эту самую сумму. А в том скрипте, который изображен, использовать простой select SumFld from AddTable where ...

А это мысль. Действительно, чего это я сумму каждый раз пересчитываю? С меня пиво.
...
Рейтинг: 0 / 0
07.08.2002, 11:50:46
    #32041432
MarchCat
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Индексы и UNION
Зря это все сведено в один запрос...
я бы развел это все по нескольким ...

При "разведении" и в голове бы все это уложилось более правильно и в процедуре бы "гладко" стало.

PS Одним словом не ремонтировать а переписать надо ...

при ремонте большого уменьшения времени выполнения не будет.
...
Рейтинг: 0 / 0
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Индексы и UNION / 18 сообщений из 18, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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