Переключение на Главную Страницу Страницы: [1] 2 3  ОтправитьПечать
Очень популярная тема (более 25 ответов) Возможно ли оптимизировать запрос к dbf (число прочтений - 7042 )
Marten
Junior Member
**
Отсутствует


1C++ rocks!

Сообщений: 44
Зарегистрирован: 02. Июля 2012
Возможно ли оптимизировать запрос к dbf
03. Июля 2012 :: 11:03
Печать  
Подскажите пожалуйста как правильнее делать соединения
СправочникАналогов LEFT JOIN СправочникТоваров LEFT JOIN РегистрПартии

Делаю так:
По СтрокаПоиска ищу различные КодАналогов из Спр.Аналоги
затем левым соединением присоединяю Спр.Номенклатура
затем левым соединением присоединяю Рег.ПартииТоваров.
Запрос рабочий.
Но кажется мне что не оптимальный. т.к. перед левым соединением
расчитывается Регистр.ПартииТоваров по всем товарам.

Как мне ограничить расчет Регистр.ПартииТоваров только теми товарами которые получаю после левого соединения с Справочником номенклатура?

Код
Выбрать все
	ТекстЗапроса = "
	|SELECT
	|	DISTINCT $СпрАналоги.КодАналогов                     AS КодАналогов,
	|	СпрНоменклатура.ID                                   AS [Ссылка $Справочник.Номенклатура],
	|	СпрНоменклатура.Code                                 AS Код,
	|	СпрНоменклатура.DESCR                                AS Наименование,
	|	ИтогиПартииТоваров.ОстатокТовара                     AS Остаток,
	|	CAST(ИтогиПартииТоваров.Стоимость AS NUMERIC(15,2))  AS Стоимость,
	|	CAST(ИтогиПартииТоваров.НДС AS NUMERIC(15,2))        AS НДС
	|FROM
	|	$Справочник.Аналоги AS СпрАналоги
	|LEFT JOIN $Справочник.Номенклатура AS СпрНоменклатура
	|		ON ($СпрНоменклатура.КодАналогов = $СпрАналоги.КодАналогов) AND
	|		   (СпрНоменклатура.IsFolder = 2) AND
	|		   (СпрНоменклатура.IsMark = '')
	|LEFT JOIN (
	|           SELECT
	|				$ИтогиПартии.Товар AS ТоварID,
	|				SUM($ИтогиПартии.ОстатокТовара) AS ОстатокТовара,
	|				SUM($ИтогиПартии.Стоимость) AS Стоимость,
	|				SUM($ИтогиПартии.НДС) AS НДС
	|			FROM
	|				$РегистрИтоги.ПартииТоваров AS ИтогиПартии
	|			WHERE
	|				(period = :ТАМесяц~~)
	|           GROUP BY
	|				$ИтогиПартии.Товар
	|			) AS ИтогиПартииТоваров
	|			ON ИтогиПартииТоваров.ТоварID = СпрНоменклатура.ID
	|
	|WHERE
	|	СпрАналоги.IsMark = '' AND
	|	(LOWER($СпрАналоги.Артикул) = :Артикул)
	|";                                                              

	База = СоздатьОбъект("OLEDBData");
	Соединение = "Provider=VFPOLEDB.1;Data Source=" + КаталогИБ() + ";Mode=ReadWrite;Collating Sequence=MACHINE";
	Рез = База.Соединение(Соединение);
    Если Рез=0 Тогда
        Сообщить("Подключение к БД не выполнено!", "!");
    КонецЕсли;
    Запрос = База.СоздатьКоманду();
    Запрос.УстановитьТекстовыйПараметр("Артикул", СтрокаПоиска);
    Запрос.УстановитьТекстовыйПараметр("ТАМесяц", НачМесяца(ПолучитьДатуТА()));
    ТЗ = Запрос.ВыполнитьИнструкцию(ТекстЗапроса);
 

  
Наверх
 
IP записан
 
Eprst
God Member
*****
Отсутствует



Сообщений: 3397
Зарегистрирован: 08. Октября 2007
Re: Возможно ли оптимизировать запрос к dbf
Ответ #1 - 03. Июля 2012 :: 11:35
Печать  
Marten писал(а) 03. Июля 2012 :: 11:03:


Как мне ограничить расчет Регистр.ПартииТоваров только теми товарами которые получаю после левого соединения с Справочником номенклатура?


Быстрее не будет.

А так, твой запрос нужно переписыть, чтоб задействовал индексы - вот тогда скорость возрастет в разы.

Но если хочешь - то запрос сразу к регистру + условие на номенклатуру, которую получаешь подзапросом.
  
Наверх
 
IP записан
 
Marten
Junior Member
**
Отсутствует


1C++ rocks!

Сообщений: 44
Зарегистрирован: 02. Июля 2012
Re: Возможно ли оптимизировать запрос к dbf
Ответ #2 - 03. Июля 2012 :: 11:49
Печать  
запрос сразу к регистру + условие на номенклатуру

Можно любой пример? (только к dbf)
  
Наверх
 
IP записан
 
Eprst
God Member
*****
Отсутствует



Сообщений: 3397
Зарегистрирован: 08. Октября 2007
Re: Возможно ли оптимизировать запрос к dbf
Ответ #3 - 03. Июля 2012 :: 12:29
Печать  
Код
Выбрать все
	ОлеДБ = СоздатьОбъект("OLEDBData");
	Соединение = "Provider=VFPOLEDB.1;Data Source=" + КаталогИБ() + ";Mode=ReadWrite;Collating Sequence=MACHINE";
	Рез = ОлеДБ.Соединение(Соединение);
	Запрос = ОлеДБ.СоздатьКоманду();
	Запрос.Выполнить("EXECSCRIPT('SET ANSI OFF')");
	Запрос.Выполнить("EXECSCRIPT('SET REPROCESS TO 60 SECONDS')");
	Запрос.Выполнить("EXECSCRIPT('SET REFRESH TO 0,-1')");
	Запрос.Выполнить("Exec('SET TABLEVALIDATE TO 0')");
	Запрос = ОлеДБ.СоздатьКоманду();

	ТекстЗапроса = "
		|   SELECT
		|		 $ИтогиПартии.Товар as [Номенклатура $Справочник.Номенклатура],
	  |		   SUM($ИтогиПартии.ОстатокТовара) AS ОстатокТовара,
	    |	     SUM($ИтогиПартии.Стоимость) AS Стоимость,
	    |				SUM($ИтогиПартии.НДС) AS НДС
		|	FROM
		|		$РегистрИтоги.ПартииТоваров ИтогиПартии
		|	WHERE
		|		DTOS(ИтогиПартии.period)+$ИтогиПартии.Товар --надеюсь, на товар есть галка отбор итогов
		|		LIKE  (DTOS(:НачПериод~~)+'_________')
		|	and $ИтогиПартии.Товар in
		|    (select СпрНоменклатура.id from  $Справочник.Номенклатура AS СпрНоменклатура
		|     where
     	|		   СпрНоменклатура.IsFolder = 2 AND СпрНоменклатура.IsMark = ''
	  |	    and $СпрНоменклатура.КодАналогов in ( SELECT $СпрАналоги.КодАналогов FROM $Справочник.Аналоги AS СпрАналоги
		|	     where СпрАналоги.IsMark = '' AND LOWER($СпрАналоги.Артикул) = :Артикул))
		|";
    Запрос.УстановитьТекстовыйПараметр("Артикул", СтрокаПоиска);
	мд = СоздатьОбъект("MetaDataWork");
	уТА()));
	ТЗ = Запрос.ВыполнитьИнструкцию(ТекстЗапроса); 



типа того, можешь и заместо where  -  inner join затолкать, если нужны еще поля
  
Наверх
 
IP записан
 
Marten
Junior Member
**
Отсутствует


1C++ rocks!

Сообщений: 44
Зарегистрирован: 02. Июля 2012
Re: Возможно ли оптимизировать запрос к dbf
Ответ #4 - 03. Июля 2012 :: 12:40
Печать  
Спасибо.
  
Наверх
 
IP записан
 
Marten
Junior Member
**
Отсутствует


1C++ rocks!

Сообщений: 44
Зарегистрирован: 02. Июля 2012
Re: Возможно ли оптимизировать запрос к dbf
Ответ #5 - 03. Июля 2012 :: 21:07
Печать  
Решил сделать упор на индексы
Все получается. Запрос выполняется в 4 раза быстрее

Только один вопрос.
Прочитал про оптимизацию индексов часть 2. На странице 2 обсуждались индексы когда идет LEFT JOIN

Пробую применить к своему запросу - получается запрос дольше выполняется т.е. не попал в индекс

Ткните носом что не так делаю:

1. Использую один индекс из множества в Спр.Номенклатура
UPPER(sp3163)+UPPER(descr)
sp3163 строка 15
descr строка 100 (так уж сложилось)

Код
Выбрать все
	|LEFT JOIN $Справочник.Номенклатура AS СпрН
	|		ON (UPPER(СпрН.sp3163)+UPPER(СпрН.descr)
	|			LIKE _________________________________________'))
	|		   AND (СпрН.IsFolder = 2)
	|		   AND (СпрН.IsMark = '')
 

  
Наверх
 
IP записан
 
Marten
Junior Member
**
Отсутствует


1C++ rocks!

Сообщений: 44
Зарегистрирован: 02. Июля 2012
Re: Возможно ли оптимизировать запрос к dbf
Ответ #6 - 03. Июля 2012 :: 22:31
Печать  
Как при LEFT JOIN использовать индекс для DBF?

индекс
UPPER(sp3163)+UPPER(descr)
sp3163 строка 15
descr строка 100
sp3056 строка 15

Код
Выбрать все
	|LEFT JOIN $Справочник.Номенклатура AS СпрН
	|		ON (UPPER(СпрН.sp3163)+UPPER(СпрН.descr)
	|			LIKE _________________________________________'))
	|		   AND (СпрН.IsFolder = 2)
	|		   AND (СпрН.IsMark = '')

 

  
Наверх
 
IP записан
 
Eprst
God Member
*****
Отсутствует



Сообщений: 3397
Зарегистрирован: 08. Октября 2007
Re: Возможно ли оптимизировать запрос к dbf
Ответ #7 - 04. Июля 2012 :: 09:14
Печать  
вот тут вот качнешь нужное для проверки, попал ли в индекс , али нет
http://www.1cpp.ru/forum/YaBB.pl?num=1210677779/15

зы: сам фокс не нужен, нужны только пару файликов от него..
  
Наверх
 
IP записан
 
Marten
Junior Member
**
Отсутствует


1C++ rocks!

Сообщений: 44
Зарегистрирован: 02. Июля 2012
Re: Возможно ли оптимизировать запрос к dbf
Ответ #8 - 04. Июля 2012 :: 11:06
Печать  
Использование индекс тэг Idd для оптимизации по технологии Rushmore таблица спрн
Уровень оптимизации Rushmore для таблица спрн: частичная

IDD = Expression id
т.е. в нужный индекс не попал.


нужен индекс VI3163 = Expression UPPER(sp3163)+UPPER(descr)

Правильную ли инструкцию для попадания в индекс использую?

Код
Выбрать все
	|LEFT JOIN $Справочник.ХХХ AS СпрХХХ
	|		ON (описание индекса
	|			LIKE (данные для индекса))
 

  
Наверх
 
IP записан
 
Marten
Junior Member
**
Отсутствует


1C++ rocks!

Сообщений: 44
Зарегистрирован: 02. Июля 2012
Re: Возможно ли оптимизировать запрос к dbf
Ответ #9 - 04. Июля 2012 :: 11:14
Печать  
придерживаюсь поста kiruha по Использование индексов (ДБФ) часть 2.

"Т.е. грубо говоря, можно придерживаться следующего простого правила :
для того, чтобы Fox использовал индекс нужно
составить обычный запрос  - как для SQL ,
но только в предложениях WHERE, JOIN - левое выражение дополнять до индекса, который хотим использовать.
И предварительно задать SET ANSI OFF"
  
Наверх
 
IP записан
 
Eprst
God Member
*****
Отсутствует



Сообщений: 3397
Зарегистрирован: 08. Октября 2007
Re: Возможно ли оптимизировать запрос к dbf
Ответ #10 - 04. Июля 2012 :: 11:36
Печать  
Код
Выбрать все
ON (STR(СпрН.sp3163,15)+STR(СпрН.descr,100)
	|			LIKE __________________________________________')) 

  
Наверх
 
IP записан
 
Eprst
God Member
*****
Отсутствует



Сообщений: 3397
Зарегистрирован: 08. Октября 2007
Re: Возможно ли оптимизировать запрос к dbf
Ответ #11 - 04. Июля 2012 :: 11:55
Печать  
хотя, с upper должно усё работать..
количество подчеркиваний, точно 100 хоть?

Запрос.Выполнить("EXECSCRIPT('SET ANSI OFF')");

есть в коде ?
  
Наверх
 
IP записан
 
Marten
Junior Member
**
Отсутствует


1C++ rocks!

Сообщений: 44
Зарегистрирован: 02. Июля 2012
Re: Возможно ли оптимизировать запрос к dbf
Ответ #12 - 04. Июля 2012 :: 12:07
Печать  
100 проверял

Запрос = База.СоздатьКоманду();
Запрос.Выполнить("EXECSCRIPT('SET ANSI OFF')");

FAILED! ICommandText::Execute(): Function argument value, type, or count is invalid.

Код
Выбрать все
	|LEFT JOIN $Справочник.Номенклатура AS СпрН
	|		ON (STR(СпрН.sp3163,15)+STR(СпрН.descr,100)
	|			LIKE __________________________________________'))
 

  
Наверх
 
IP записан
 
Eprst
God Member
*****
Отсутствует



Сообщений: 3397
Зарегистрирован: 08. Октября 2007
Re: Возможно ли оптимизировать запрос к dbf
Ответ #13 - 04. Июля 2012 :: 12:13
Печать  
Это ошибка на эту команду ?
или на сам текст запроса ?
  
Наверх
 
IP записан
 
Marten
Junior Member
**
Отсутствует


1C++ rocks!

Сообщений: 44
Зарегистрирован: 02. Июля 2012
Re: Возможно ли оптимизировать запрос к dbf
Ответ #14 - 04. Июля 2012 :: 12:16
Печать  
Только на SET

sp3163 строка 15
descr строка 100
sp3056 строка 15
Поля у меня уже такой длинны (проверял в отладке) зачем SET?
  
Наверх
 
IP записан
 
Переключение на Главную Страницу Страницы: [1] 2 3 
ОтправитьПечать