Имя пользователя:
Пароль:
 | Правила  

Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Программирование и базы данных » MSFT SQL Server - [решено] Оптимизация запроса

Ответить
Настройки темы
MSFT SQL Server - [решено] Оптимизация запроса

Аватара для xctr

Старожил


Сообщения: 200
Благодарности: 16


Конфигурация

Профиль | Отправить PM | Цитировать


Здравствуйте!
Ребят прошу вашей помощи в оптимизации SQL запроса.
Задача:
Есть очень большая таблица (7 миллионов и это только за год), данные могут быть разбросаны по всей таблице и нужные данные могут быть в переделе одной недели т.е. в пределах примерно в 300 тысяч строк.
Нужно найти повторения строк в разрезе одного документа, и определить что данные повторения выполняются последовательно одним сотрудником. И в конце посчитать сколько раз повторения строк были выполнены сотрудником не последовательно, либо вообще другим сотрудником.
Кусок таблицы:



Сейчас получился вот такой запрос:
Код: Выделить весь код
DECLARE @StartDate as datetime
DECLARE @FinishDate as datetime
DECLARE @ExternalCode as varchar(30)
set @StartDate = '2013-12-09 08:00:15.100'
set @FinishDate = GETDATE()
--set @Document

DECLARE @doc table (
TID int,
Documents varchar(20) null,
Article varchar(20) null,
NameRU varchar(255) null,
SourseLocations varchar(20) null,
SourseOS varchar(20) null,
ProductionResources varchar(50) null,
TargetOS varchar(20) null,
Quantity int null,
Units varchar(20) null,
FinishDate datetime null,
Namber int IDENTITY (1,1) not null,
Quantity_SKU int null,
Razriv int null
)


/*Заполняем временную таблицу данными с сортировкой (Документ, Сотрудник, Дата/Время выполнения)*/
insert into @doc (TID, Documents, Article, NameRU, SourseLocations, SourseOS, ProductionResources, TargetOS, Quantity, Units, FinishDate)

select
	mp.tid,
	DR.ExternalCode,
	m.NameEN,
	m.NameRU,
	MP.SourceLocationName,
	MP.SourceStorageObjectName,
	MP.TargetLocationName,
	MP.TargetStorageObjectName,
	MP.BaseQuantity,
	MP.AlternateMaterialUnitName,
	mp.FinishDate
from
	hdr_DeliveryRequest as DR with (nolock)
	join Transactions as T1 with (nolock) on DR.Transaction_id = T1.tid
	join Transactions as T2 with (nolock) on T2.ParentTransaction_id = T1.tid
	join Transactions as T3 with (nolock) on T3.ParentTransaction_id = T2.tid
	join hdr_MaterialPicking as MP with (nolock) on MP.Transaction_id = T3.tid
	join Materials as M with (nolock) on MP.Material_id = M.tid
	where mp.FinishDate > ISNULL(@StartDate, mp.FinishDate)
	and mp.FinishDate < ISNULL(@FinishDate, mp.FinishDate)
	and DR.ExternalCode like ISNULL(@ExternalCode, DR.ExternalCode)
	and mp.TransactionStatus = 1
	group by
	mp.tid,
	DR.ExternalCode,
	m.NameEN,
	m.NameRU,
	MP.SourceLocationName,
	MP.SourceStorageObjectName,
	MP.TargetLocationName,
	MP.TargetStorageObjectName,
	MP.BaseQuantity,
	MP.AlternateMaterialUnitName,
	mp.FinishDate
	order by 
	DR.ExternalCode,
	MP.TargetLocationName,
	mp.FinishDate
	
	/*Считаем количество повторении позиции внутри документа, в штучно/коробочном разрезе*/
	DECLARE @Document as varchar(20)
	DECLARE @TID as INT
	DECLARE @ARTICLE as varchar(20)
	DECLARE @Quantity_SKU as int
	DECLARE @Unit as varchar(10)
	
	while (select COUNT(*) from @doc where Quantity_SKU is null) > 0
	BEGIN
		
	select 
	  @TID = t.TID,
	  @ARTICLE = t.Article,
	  @Document = t.Documents,
	  @Unit = t.Units
	from
	(select TOP 1 TID, Article, Documents, Units from @doc where Quantity_SKU is null order by TID DESC) as t
	
	if
	@Unit = 'Штука'
	select @Quantity_SKU = COUNT(Article) from @doc where Documents = @Document and Article = @ARTICLE and Units like 'Штука'
	else 
	select @Quantity_SKU = COUNT(Article) from @doc where Documents = @Document and Article = @ARTICLE and Units not like 'Штука'
	
	UPDATE @doc SET Quantity_SKU = @Quantity_SKU where TID = @TID
	end
	
	/*Считаем разрывы, на основе разницы местоположения строк одинокового товара внутри одного документа*/
	DECLARE @Document2 as varchar(20)
	DECLARE @TID2 as INT
	DECLARE @ARTICLE2 as varchar(20)
	DECLARE @Quantity_SKU2 as int
	DECLARE @Unit2 as varchar(10)
		
	while (select COUNT(*) from @doc where Razriv is null) > 0
	
	BEGIN
	select 
	  @TID2 = t2.TID,
	  @ARTICLE2 = t2.Article,
	  @Document2 = t2.Documents,
	  @Quantity_SKU2 = t2.Quantity_SKU,
	  @Unit2 = t2.Units
	from
	(select TOP 1 TID, Article, Documents, Quantity_SKU, Units from @doc where Razriv is null order by Documents, ProductionResources, FinishDate) as t2
	
	if
	@Unit2 = 'Штука'
	update @doc set Razriv = (select MAX(Namber) + 1 from @doc where Documents = @Document2 and Article = @ARTICLE2 and Units like 'Штука') - (select MIN(Namber) from @doc where Documents = @Document2 and Article = @ARTICLE2 and Units like 'Штука')
	where TID = @TID2 and Razriv is null and Units like 'Штука'
	else
	update @doc set Razriv = (select MAX(Namber) + 1 from @doc where Documents = @Document2 and Article = @ARTICLE2 and Units not like 'Штука') - (select MIN(Namber) from @doc where Documents = @Document2 and Article = @ARTICLE2 and Units not like 'Штука')
	where TID = @TID2 and Razriv is null and Units not like 'Штука'
	end
	
	/*Выводим разрывы, на основе отличия местоположения позиции одинакового товара внутри документа, и количества повторении строки с одинаковым товаром внутри документа*/		
	select COUNT(*) as 'Разрыв штук' from @doc where Quantity_SKU <> Razriv and Units like 'Штука'
	select COUNT(*) as 'Разрыв коробок' from @doc where Quantity_SKU <> Razriv and Units not like 'Штука'
Отрабатывает данный запрос за 14 минут всего 20 тысяч строк, это очень медленно, как оптимизировать, у меня уже идей нет.

Отправлено: 15:28, 09-12-2013

 

Аватара для Delirium

Ветеран


Сообщения: 5624
Благодарности: 936

Профиль | Отправить PM | Цитировать


Что говорит план выполнения запроса?

-------

Пройденные курсы:
[Microsoft №10174 Sharepoint], [SharePoint]
Мои проекты:[CheckAdmins], [NetSend7], [System Uptime], [Remote RAdmin LogViewer],[Netdom GDI], [Holidays - напоминалка о днях рождения]

А я офис-гуру :)


Отправлено: 06:28, 18-12-2013 | #2



Для отключения данного рекламного блока вам необходимо зарегистрироваться или войти с учетной записью социальной сети.

Если же вы забыли свой пароль на форуме, то воспользуйтесь данной ссылкой для восстановления пароля.


Аватара для xctr

Старожил


Сообщения: 200
Благодарности: 16

Профиль | Отправить PM | Цитировать


Решение:
Добавление индексов на переменную таблицу.
Можно конечно отказаться от одного из циклов, но заморачиваться не хочется.

Итог:
Скорость работы запроса выросла в три раза, что в принципе устраивает.

Полученный опыт:
Использовать циклы только в крайнем случае.
Это сообщение посчитали полезным следующие участники:

Отправлено: 15:24, 15-01-2014 | #3



Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Программирование и базы данных » MSFT SQL Server - [решено] Оптимизация запроса

Участник сейчас на форуме Участник сейчас на форуме Участник вне форума Участник вне форума Автор темы Автор темы Шапка темы Сообщение прикреплено

Похожие темы
Название темы Автор Информация о форуме Ответов Последнее сообщение
Установка - оптимизация alik777 Microsoft Windows 2000/XP 1 24-07-2010 22:58
Оптимизация запроса venuko Вебмастеру 7 06-04-2009 00:11
Оптимизация запроса venuko Вебмастеру 7 27-02-2009 12:10
Службы - Оптимизация Malfatto Microsoft Windows Vista 2 06-09-2008 15:08
Оптимизация pashka-88 Хочу все знать 2 30-10-2005 20:49




 
Переход