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

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

Можно сделать отдельную табличку с полями, общими для двух таблиц на которые повесить нужные триггера.
...
Рейтинг: 0 / 0
Индексы и UNION
    #32040932
Фотография Garya
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Garya Привилегированный пользователь
Участник
Если в двух таблицах нет и не может быть схожих записей, то вместо UNION необходимо использовать UNION ALL. При таком объединении не будет попарно производиться сравнение всех записей из этих таблиц для выявления повторяющихся записей (изкоторых пир использовании UNION необходимо включить в результирующий набор только одну копию). И работать все будет гораздо быстрее.
...
Рейтинг: 0 / 0
Индексы и UNION
    #32040946
Фотография MiCe
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
согласен с Garya...
на таком принципе обычно стороятся хранилища.....
...
Рейтинг: 0 / 0
Индексы и UNION
    #32040972
Roman M
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Спасибо, Garya, последовал Вашему совету, но, к сожалению, быстродействие не увеличилось.
...
Рейтинг: 0 / 0
Индексы и UNION
    #32040976
Фотография MiCe
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
покажите структуру с индексами и текст вью...
...
Рейтинг: 0 / 0
Индексы и UNION
    #32041109
Roman M
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Ух, не знаю, захочет ли кто-нибудь прочитать столько кода, но все-таки:

Текст вьюхи с 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
Индексы и UNION
    #32041146
Фотография Garya
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Garya Привилегированный пользователь
Участник
> Все таблицы проиндексированы по полям, присутствующим в Where триггера...

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

View открывается 16 секунд. 43000 строк.
Не знаю, много это или мало
...
Рейтинг: 0 / 0
Индексы и UNION
    #32041260
Фотография MiCe
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
а что показывает план запроса на вьюхах?
...
Рейтинг: 0 / 0
Индексы и UNION
    #32041265
Зайцев Фёдор
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Правильно не изменилось.
IsNull как раз почти не тормозит. Я бы сказал "совсем не тормозит", но не было случая проверить ВСЕ варианты.
...
Рейтинг: 0 / 0
Индексы и UNION
    #32041279
Roman M
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
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
Индексы и UNION
    #32041284
Фотография MiCe
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
помоему при таком количестве он вьхи засовывает в темптабл....
ща еще подемаю...
...
Рейтинг: 0 / 0
Индексы и UNION
    #32041300
Фотография Garya
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Garya Привилегированный пользователь
Участник
У тебя слишком много агрегатных функций, каждая из которых вычисляется отдельным сканированием. Попробуй уменьшить количество подзапросов и/или агрегатных функций. Мне, в частности, не понятно, зачем в первом подзапросе нужно вычислять приходы ДО текущей дате (по условию <), а во втором отдельно приходы по текущей дате (по условию =). Нельзя их как-нибудь объединить в один подзапрос по условию <=?
А вот если приходы и расходы хранить вообще в одной таблице, то вместо всей груды подзапросов достаточно вообще одного, у которого внутри summ() находится case, который приходы суммирует с плюсом, а расходы - с минусом.
Если этот вариант не нравится, обрати внимание на еще одно решение, предложенное в моем предыдущем постинге (с триггерами, отслеживающими итоговые данные).
...
Рейтинг: 0 / 0
Индексы и UNION
    #32041305
Roman M
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
2 Garya:

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

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

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

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

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

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

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

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

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

Я не про дату, а про сумму. Для того чтобы не писать select sum(Prohod.Summa) form Prihod, можно завести вспомогательную таблицу, в которой триггерами на Insert/update/delete, прицепленными к таблице Prihod , получать эту самую сумму. А в том скрипте, который изображен, использовать простой select SumFld from AddTable where ...
...
Рейтинг: 0 / 0
Индексы и UNION
    #32041416
Roman M
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
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
Индексы и UNION
    #32041432
Фотография MarchCat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Зря это все сведено в один запрос...
я бы развел это все по нескольким ...

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

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

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


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