Переключение на Главную Страницу Страницы: 1 ОтправитьПечать
Горячая тема (более 10 ответов) Поиск по номеру документа (число прочтений - 4468 )
Insuran
YaBB Newbies
*
Отсутствует


1C++ rocks!

Сообщений: 5
Зарегистрирован: 23. Июля 2013
Пол: Мужской
Поиск по номеру документа
12. Июня 2014 :: 07:38
Печать  
Доброго дня всем!

По одному из видов документов, есть необходимость поиска
документа по неполному номеру.

Сейчас реализовано так:
Код
Выбрать все
SELECT
	Жур.IDDoc as [Договор $Документ.Договор]
FROM
  _1SJourn as Жур WITH (NOLOCK)
WHERE  
	Жур.IDDocDef = 4375 -- тут вид документа
	AND PATINDEX ('%тут номер для поиска%' , Жур.DocNo) > 0 



База растет, и все это дело уже не устраивает по скорости
(сейчас, в зависимости от загрузки сервера, время колеблется от 10 секунд и выше ).

Попробовал ограничить выборку за период
Код
Выбрать все
AND Жур.Date_Time_IDDoc BETWEEN 'датаначала' AND 'датаконцаZ' 

минимальный период в котором надо искать от текущей даты минус три года, выигрыша по скорости нет.

Еще один вариант, который пришел в голову:
- сделал рядом еще одну базу с одной таблицей (поля IDDoc и DocNo)
- заполнил таблицу, тем что было на момент создания базы
- настроил джоб добавлять недостающие записи в таблицу

В итоге запрос для поиска получился вида:
Код
Выбрать все
SELECT
	Жур.IDDoc as [Договор $Документ.Договор]
FROM
  _1SJourn as Жур WITH (NOLOCK)
WHERE
	Жур.IDDOC IN (SELECT IDDOC FROM testDogNumber.dbo.dogNumbers WHERE PATINDEX ('%тут номер для поиска%', DocNo) > 0)
 


проверил не тестовой базе, скорость вроде стала получше (до 5 секунд).

Но что-то терзают смутные сомнения, туда ли я иду...  Нерешительный

Вопрос в чем, может кто подскажет были ли у кого еще такие проблемы, и посоветуете как лучше решить?

MSSQL 2008 r2
Код
Выбрать все
SELECT
	COUNT(*)
FROM
  _1SJourn as Жур WITH (NOLOCK) 


возвращает 15533420 записей...

Заранее спасибо тем кто откликнется!
  
Наверх
 
IP записан
 
varelchik_f
Junior Member
**
Отсутствует


1C++ rocks!

Сообщений: 36
Местоположение: Киев
Зарегистрирован: 10. Апреля 2014
Пол: Мужской
Re: Поиск по номеру документа
Ответ #1 - 12. Июня 2014 :: 11:12
Печать  
А like использовать не пробовал?
  
Наверх
 
IP записан
 
varelchik_f
Junior Member
**
Отсутствует


1C++ rocks!

Сообщений: 36
Местоположение: Киев
Зарегистрирован: 10. Апреля 2014
Пол: Мужской
Re: Поиск по номеру документа
Ответ #2 - 12. Июня 2014 :: 11:17
Печать  
select * from _1sjourn
where
docno like '%2563%'
and
iddocdef=768
вполне сносно отрабытывает на _1sjourn c 3 мн. записей за 3 сек.
ну та твоей думаю за сек 15-20.
  
Наверх
 
IP записан
 
varelchik_f
Junior Member
**
Отсутствует


1C++ rocks!

Сообщений: 36
Местоположение: Киев
Зарегистрирован: 10. Апреля 2014
Пол: Мужской
Re: Поиск по номеру документа
Ответ #3 - 12. Июня 2014 :: 11:20
Печать  
И это без ограничения периода.
  
Наверх
 
IP записан
 
Insuran
YaBB Newbies
*
Отсутствует


1C++ rocks!

Сообщений: 5
Зарегистрирован: 23. Июля 2013
Пол: Мужской
Re: Поиск по номеру документа
Ответ #4 - 12. Июня 2014 :: 11:34
Печать  
varelchik_f писал(а) 12. Июня 2014 :: 11:17:
select * from _1sjourn
where
docno like '%2563%'
and
iddocdef=768
вполне сносно отрабытывает на _1sjourn c 3 мн. записей за 3 сек.
ну та твоей думаю за сек 15-20.


пробовал... по ощущениям , даже хуже становится  Нерешительный
  
Наверх
 
IP записан
 
Igor Nikolaenko
Junior Member
**
Отсутствует


1C++ rocks!

Сообщений: 47
Зарегистрирован: 01. Апреля 2010
Re: Поиск по номеру документа
Ответ #5 - 12. Июня 2014 :: 13:55
Печать  
Пользователи, при поиске по номеру документа, наверняка вводят последние цифры номера. Может всех устроить вариант ввода последних 4(3) цифр. Тогда поиск можно делать через сравнении, т.е. с использованием индекса, т.к. сейчас идет перебор всех строк.
  
Наверх
 
IP записан
 
ADirks
1c++ developer
1c++ moderator
Отсутствует


А нужны ли мы нам?

Сообщений: 692
Местоположение: Новосибирск
Зарегистрирован: 22. Мая 2006
Пол: Мужской
Re: Поиск по номеру документа
Ответ #6 - 16. Июня 2014 :: 06:52
Печать  
Какая интересная тема Улыбка
Оказывается, я как последний лошара не попадал в индекс DocNo
а надо во так:
Код
Выбрать все
SELECT
	жДок.идДок13 [Док $Документ]
FROM
	ЖурналДокументов жДок
WHERE
	жДок.DocNo = '01400884'
	AND жДок.IDDocDef IN (15124)
	AND (жДок.DNPrefix like '     15124%')
ORDER BY
	жДок.Date_Time_IDDoc Desc 



т.е. для попадания в индекс нужно условие по DNPrefix. Правда, я не знаю, что там за пробелы впереди. Код базы в УРБД?
  
Наверх
 
IP записан
 
Satans Claws
God Member
*****
Отсутствует


1C++ rocks!

Сообщений: 721
Зарегистрирован: 29. Ноября 2010
Re: Поиск по номеру документа
Ответ #7 - 16. Июня 2014 :: 08:40
Печать  
ADirks писал(а) 16. Июня 2014 :: 06:52:
Правда, я не знаю, что там за пробелы впереди. Код базы в УРБД?


Код базы УРБД - всего 3 символа.
А если IDDocDef являет собой 4 цифры - сколько будет ведущих пробелов?

ЗЫ А не идентификатор ли периода там должен быть?
  
Наверх
 
IP записан
 
Satans Claws
God Member
*****
Отсутствует


1C++ rocks!

Сообщений: 721
Зарегистрирован: 29. Ноября 2010
Re: Поиск по номеру документа
Ответ #8 - 16. Июня 2014 :: 09:08
Печать  
Использовав скилл "звонок другу" имею следующее:
в УРБД, для IdDocDef = 8073 DNPrefix = '     8073' (5 пробелов + IdDocDef)

Кстати, надо еще посмотреть, что будет в DNPrefix для документов с назначенным нумератором. По идее - должно быть "5 пробелов + Идентификатор нумератора"
  
Наверх
 
IP записан
 
ADirks
1c++ developer
1c++ moderator
Отсутствует


А нужны ли мы нам?

Сообщений: 692
Местоположение: Новосибирск
Зарегистрирован: 22. Мая 2006
Пол: Мужской
Re: Поиск по номеру документа
Ответ #9 - 16. Июня 2014 :: 09:32
Печать  
В общем, пока исследования показали следующее
Код
Выбрать все
Функция сзДокументыПоНомеру(Знач НомерДок, НачДата, КонДата, Знач ВидДок) Экспорт
	Если ТипЗначения(ВидДок) = 2 Тогда
		ВидДок = СтрокуВСписок(ВидДок, ",", 1);
	КонецЕсли;
	стрВидДок = ""; зпт = "";
	стрНДПрефикс = ""; зпт_префикс = "";
	Для н = 1 По ВидДок.РазмерСписка() Цикл
		Вид = ВидДок.ПолучитьЗначение(н);
		стрВидДок = стрВидДок + зпт + "$ВидДокумента."+Вид;
		зпт = ",";

		//Вычисляем DNPrefix
		Нумератор = Метаданные.Документ(Вид).Нумератор;
		Если Нумератор.Выбран() = 1 Тогда
			ИДОбъект = РадугаСервис.ИДОбъекта(Нумератор);
		Иначе
			ИДОбъект = РадугаСервис.ИДДокумента(Вид);
		КонецЕсли;
		стрИДОбъект = Прав("	    "+ИДОбъект, 10);
		стрНДПрефикс = стрНДПрефикс + зпт_префикс + "жДок.DNPrefix like '"+стрИДОбъект+"%'";
		зпт_префикс = " OR ";
	КонецЦикла;

	Если Найти(НомерДок, ",") > 0 Тогда
		стрФильтр = стрФильтрПоСтроке("жДок.DocNo", НомерДок);
	ИначеЕсли Найти(НомерДок, " ") > 0 Тогда
		стрФильтр = стрФильтрПоСтроке("жДок.DocNo", НомерДок);
	ИначеЕсли Найти(НомерДок, "%") > 0 Тогда
		стрФильтр = стрФильтрПоСтроке("жДок.DocNo", НомерДок);
	Иначе
		стрФильтр = "жДок.DocNo = '"+НомерДок+"'";
	КонецЕсли;

	ТекстЗапроса = "Set NoCount ON
	|SELECT
	|	жДок.идДок13 [Док $Документ]
	|FROM
	|	ЖурналДокументов жДок
	|WHERE
	|	жДок.Date_Time_IDDoc > :НачДата AND жДок.Date_Time_IDDoc < :КонДата
	|	AND "+стрФильтр+"
	|	AND жДок.IDDocDef IN ("+стрВидДок+")
	|	AND ("+стрНДПрефикс+")
	|ORDER BY
	|	жДок.Date_Time_IDDoc Desc
	|";

	ЗапросСКЛ.УстановитьТекстовыйПараметр("НачДата", ?(ПустоеЗначение(НачДата) = 0, НачДата, '01.01.1753'));
	ЗапросСКЛ.УстановитьТекстовыйПараметр("КонДата", ?(ПустоеЗначение(КонДата) = 0, КонДата+1, '01.01.9999'));
	сз = СоздатьОбъект("СписокЗначений");
	ЗапросСКЛ.ВыполнитьИнструкцию(ТекстЗапроса, сз);

	Для н = 1 По сз.РазмерСписка() Цикл
		Док = сз.ПолучитьЗначение(н);
		сз.УстановитьЗначение(н, Док, ""+Док+" от "+Док.ДатаДок);
	КонецЦикла;

	Возврат сз;
КонецФункции
 

  
Наверх
 
IP записан
 
Insuran
YaBB Newbies
*
Отсутствует


1C++ rocks!

Сообщений: 5
Зарегистрирован: 23. Июля 2013
Пол: Мужской
Re: Поиск по номеру документа
Ответ #10 - 16. Июня 2014 :: 11:49
Печать  
Satans Claws писал(а) 16. Июня 2014 :: 09:08:
Использовав скилл "звонок другу" имею следующее:
в УРБД, для IdDocDef = 8073 DNPrefix = '     8073' (5 пробелов + IdDocDef)

Кстати, надо еще посмотреть, что будет в DNPrefix для документов с назначенным нумератором. По идее - должно быть "5 пробелов + Идентификатор нумератора"


хм... добавление в запрос  DNPrefix = (5 пробелов + IdDocDef) дало очень даже хороший результат. Пока еще тестирую, но однозначно быстрее... Спасибо огромное!
  
Наверх
 
IP записан
 
ADirks
1c++ developer
1c++ moderator
Отсутствует


А нужны ли мы нам?

Сообщений: 692
Местоположение: Новосибирск
Зарегистрирован: 22. Мая 2006
Пол: Мужской
Re: Поиск по номеру документа
Ответ #11 - 16. Июня 2014 :: 12:57
Печать  
(10) Всё-таки учти замечание про длину IDDocDef и наличие нумераторов. Под идВидДок10 (или идНумератор10) отведено первые 10 символов (100% уверенности нет, но похоже что так). Поэтому условие по DNPrefix надо как-то так генерить:
Код
Выбрать все
Нумератор = Метаданные.Документ(Вид).Нумератор;
Если Нумератор.Выбран() = 1 Тогда
	ИДОбъект = РадугаСервис.ИДОбъекта(Нумератор);
Иначе
	ИДОбъект = РадугаСервис.ИДДокумента(Вид);
КонецЕсли;
стрИДОбъект = Прав("	    "+ИДОбъект, 10);
стрНДПрефикс = "жДок.DNPrefix like '"+стрИДОбъект+"%'";
 

  
Наверх
 
IP записан
 
Insuran
YaBB Newbies
*
Отсутствует


1C++ rocks!

Сообщений: 5
Зарегистрирован: 23. Июля 2013
Пол: Мужской
Re: Поиск по номеру документа
Ответ #12 - 16. Июня 2014 :: 13:26
Печать  
ADirks писал(а) 16. Июня 2014 :: 12:57:
(10) Всё-таки учти замечание про длину IDDocDef и наличие нумераторов. Под идВидДок10 (или идНумератор10) отведено первые 10 символов (100% уверенности нет, но похоже что так). Поэтому условие по DNPrefix надо как-то так генерить


спасиб, глянул у себя (для моего частного случая  IDDocDef = 4375)
Код
Выбрать все
	SELECT
		COUNT(*)
	FROM
	  _1SJourn as Жур WITH (NOLOCK)
	WHERE  
		Жур.IDDocDef = 4375 


и
Код
Выбрать все
	SELECT
		COUNT(*)
	FROM
	  _1SJourn as Жур WITH (NOLOCK)
	WHERE  
		Жур.DNPrefix = '      4375' 



одинаково, так что буду принимать за правильно.
  
Наверх
 
IP записан
 
Переключение на Главную Страницу Страницы: 1
ОтправитьПечать