|
SQL2008 + 1c77, 100% загрузка CPU сервера пока не зайдет админ в 1С | ☑ | ||
---|---|---|---|---|
0
Dmitriy Kolyasnikov
17.08.10
✎
22:01
|
вопросы запуска тут не обсуждаю, перегнал базу в 2008, всё запустилось само, делов не знаю :)
проблема уже была описана здесь: http://www.forum.mista.ru/topic.php?id=385485&page=1#55 у меня в точности это же происходит на 2008 SQL. Раз на раз не приходится, иногда возникает трабл, иногда нет. Если возникает - то возникает у всех (косяк проявляется со стороны SQL), любое обращение к базе любого из пользователей вызывает 100% загрузку одного процессора на сервере секунд на 10-30. Если проблема проходит - то проходит так же резко у всех (после входа в 1С пользователя с админскими правами). Кому-то удалось понять корни проблемы и почему она снимается запуском 1С? Сам склоняюсь к тому, что косяки начинаются когда пользователь обращается всё к тем же подчиненным документам. Но иногда начинается, а иногда нет - всё летает. И как проблему может устранять вход нового пользователя в 1С? нипанятна... |
|||
1
МихаилМ
17.08.10
✎
22:16
|
ну собирите статистику скл профайлером (только вместе с планом запроса)
И раскажите про решение (какие индексы изменили, какие секционировали) |
|||
2
mad hatter
18.08.10
✎
00:37
|
не замечал такого
может дело всетке не в 2008 |
|||
3
SnarkHunter
18.08.10
✎
00:39
|
При работе с нештатным софтом может происходить все что угодно...
|
|||
4
smaharbA
18.08.10
✎
06:59
|
есть такая фигня, менял некоторые индексы, но это только общее здоровье, а эффект ступора сохранился, с применением ИБП на недосервере несколько снизилась частота его появления, но само явление не пропало, специальный человек заходит и выходит из базы - с какой периодичностью не спрашивал, просто сказал будешь облегчатором )))
|
|||
5
Dmitriy Kolyasnikov
18.08.10
✎
08:06
|
(1) сравнил планы при тормозах и без них - разницы не увидел
как я понял по профайлеру (из того, что потестил) тормоза на этих операциях: FETCH API_CURSOR0000000000000010 exec sp_cursorfetch 180150049,1,0,1 (4) так да, если бы проблема была в индексах - она бы не пропадала от входа пользователя :) Что неужели всё так плохо и нас только двое с этой проблемой на весь рунет? :) надо тогда найти, что есть общего в наших конфах :) у меня сильно переписанная комплексная. У меня очень активно используются подчиненные документы. Так вот, если нет ничего открытого, что может обращаться к подчиненным документам, то трабл не возникает! например, когда идут тормоза, если ни у кого не открыто ничего, что может обращаться к подчиненным документам, то справочник номенклатуры работает очень быстро. Наблюдается ли у Вас такое? у меня в журналах есть графы отбора (по большей части остались с тех времен когда база была 10 гиг на dbf :) ): Контрагент: половина документов по полю контрагент Склад: --//-- склад ФизЛицо: --//-- ФизЛицо Сотрудник: --//-- Сотрудник Номенклатура: --//-- Документ.ЗаказПоставщику.Номенклатура И! есть такое: ОснованиеТранспорт: --//-- Документ.ЗаявкаТранспорт.ДокументОснование |
|||
6
Dmitriy Kolyasnikov
18.08.10
✎
08:08
|
коряво текст отформатировался, всё что отформатировалось под модуль 1С читать как просто текст (описаение граф отбора)
|
|||
7
Dmitriy Kolyasnikov
18.08.10
✎
08:26
|
(2) дело не в сетке, плохая сетка не может загрузить проц SQL-сервера на 100% :)
|
|||
8
Z1
18.08.10
✎
09:30
|
(0) Сколько всего документов в базе ?
select count(*) from _1sjourn(nolock) сколько приращений документов в день. Опиши железо сервера. сколько пользователей работает. Какая операц. система под sql как часто обновляется статистика. Самый простой способ для тебя пеерписать подчиненые документы через прямой запрос 1с++. |
|||
9
Dmitriy Kolyasnikov
18.08.10
✎
10:16
|
(8) в базе 1,7 млн документов
прирост: 1000-2000 док-в в день сервер: 2 4-хядерных оптерона 2.8, 16 гиг памяти, под файл базы рейд 10 на сас-винтах (чтение 250-400 мб/с), всё остальное на другом разделе на зеркале. пользователей нет, пока тестирую :) по статистике мои знания очень скупы, могу только сказать, что перепробовал комбинации "автоматическое обновление", "Автоматическое создание", "Асинхронное обновление" - изменений нет. Сейчас стоит создание true, обновления - false. реиндекс базы делал, эффекта ноль. Переписать на 1с++ не проблема. Гемор, но не проблема. Проблема в том, что проблема то есть, то нет... работает же всё через раз :( --------------------------------------------------------- сейчас посмотрел фрагментацию индексов - есть некоторые до 70% доходят. Прогнал следущий код, SQL написал, что отработал, написал где-то ребилд, где-то реорганизе, но фрагментация не изменилась :( -- Ensure a USE <databasename> statement has been executed first. SET NOCOUNT ON; DECLARE @objectid int; DECLARE @indexid int; DECLARE @partitioncount bigint; DECLARE @schemaname nvarchar(130); DECLARE @objectname nvarchar(130); DECLARE @indexname nvarchar(130); DECLARE @partitionnum bigint; DECLARE @partitions bigint; DECLARE @frag float; DECLARE @command nvarchar(4000); DECLARE @db_id SMALLINT; -- Тут прописываем вместо WB5 имя своей базы SET @db_id = DB_ID(N'ACT'); -- Conditionally select tables and indexes from the sys.dm_db_index_physical_stats function -- and convert object and index IDs to names. SELECT object_id AS objectid, index_id AS indexid, partition_number AS partitionnum, avg_fragmentation_in_percent AS frag INTO #work_to_do FROM sys.dm_db_index_physical_stats (@db_id, NULL, NULL , NULL, 'LIMITED') WHERE avg_fragmentation_in_percent > 5.0 AND fragment_count > 0 AND index_id > 0; --В строке выше указываем процент фрагментации ниже которого таблицы не трогаем --и количество фрагментаций, процент может быть большой при маленьких индексах -- Declare the cursor for the list of partitions to be processed. DECLARE partitions CURSOR FOR SELECT * FROM #work_to_do; -- Open the cursor. OPEN partitions; -- Loop through the partitions. WHILE (1=1) BEGIN; FETCH NEXT FROM partitions INTO @objectid, @indexid, @partitionnum, @frag; IF @@FETCH_STATUS < 0 BREAK; SELECT @objectname = QUOTENAME(o.name), @schemaname = QUOTENAME(s.name) FROM sys.objects AS o JOIN sys.schemas as s ON s.schema_id = o.schema_id WHERE o.object_id = @objectid; SELECT @indexname = QUOTENAME(name) FROM sys.indexes WHERE object_id = @objectid AND index_id = @indexid; SELECT @partitioncount = count (*) FROM sys.partitions WHERE object_id = @objectid AND index_id = @indexid; -- 30 is an arbitrary decision point at which to switch between reorganizing and rebuilding. IF @frag < 30.0 SET @command = N'ALTER INDEX ' + @indexname + N' ON ' + @schemaname + N'.' + @objectname + N' REORGANIZE'; IF @frag >= 30.0 SET @command = N'ALTER INDEX ' + @indexname + N' ON ' + @schemaname + N'.' + @objectname + N' REBUILD'; IF @partitioncount > 1 SET @command = @command + N' PARTITION=' + CAST(@partitionnum AS nvarchar(10)); EXEC (@command); PRINT N'Executed: ' + @command+N' процент фрагментации был: '+QUOTENAME(@frag); --PRINT N'Executed: ' + @command; END; -- Close and deallocate the cursor. CLOSE partitions; DEALLOCATE partitions; |
|||
10
Dmitriy Kolyasnikov
18.08.10
✎
10:32
|
(8) SQL 2008R2 стоит на 2008 сервере (стандарт)
|
|||
11
Z1
18.08.10
✎
10:41
|
(9) избавление от дефрагментации поможет но не спасет
( дефрагментацию и обновление статистики лучше делать всегда каждый день ночью) проблема началась с sql2005. точнее проблема не в sql а в плохом запросе который генериться из 1с когда НЕ ЗАДАН интервал подчиненных документов старшая дата береться равной 30.12.9999 ( а надо 31 или вообще не ставить это условие). Проблема решения : Если стандартный 1с то всегда в журналеПодчиненных документов выставлять интервал дат ( Для встроенного языка ВыбратьПодчиненныеДокументы тоже всегда ставить диапозон дат. Если нужна производительность то перепиши через 1с++ пример смотри здесь SQL 2005 и ВыбратьПодчиненныеДокументы() Почему то работает то нет Описание относиться когда нет доработток : Если таблица _1sjourn расположена в буфере данных то работает быстро(когда входит второй пользователь она подгружается в буфер) иначе sql2008 вынужден прогнать всю _1sjourn через буфер данных а это и есть время а при слабой дисковой системе полная и загрузка процессора. |
|||
12
smaharbA
18.08.10
✎
10:43
|
(9) у меня база на порядок меньше
|
|||
13
mad hatter
18.08.10
✎
10:44
|
чтото слышал про приблуду, перехватывающую 1С-ные запросы.. у Ромикса вроде
|
|||
14
smaharbA
18.08.10
✎
10:44
|
(13) к теме не имеет отношения
|
|||
15
mad hatter
18.08.10
✎
10:45
|
нечто похожее у меня недавно было на 2005... и там тоже Оптерон..
|
|||
16
smaharbA
18.08.10
✎
10:46
|
(15) у мне дуо, проблема давняя и на 2008 впереди планеты всей был
|
|||
17
Dmitriy Kolyasnikov
18.08.10
✎
10:49
|
(14) там запрос из формы журнала перехватывается ВК и отправляется уже свой переделанный.
|
|||
18
smaharbA
18.08.10
✎
10:50
|
(11) похоже, если в (0) тоже много ВыбратьПодчиненныеДокументы
в моей конфе вовсю задействовано ВыбратьПодчиненныеДокументы |
|||
19
smaharbA
18.08.10
✎
10:51
|
(17) это понятно, но тема как понимаю о нахождении первопричины ?
|
|||
20
smaharbA
18.08.10
✎
10:51
|
(17) у тебя используется ВыбратьПодчиненныеДокументы активно в журналах и доках ?
|
|||
21
mad hatter
18.08.10
✎
10:51
|
седня специально понаблюдаю за 2008.. не замечал за ним такого
но там, по моему, вапче подчиненные доки не используются)))) |
|||
22
Dmitriy Kolyasnikov
18.08.10
✎
10:54
|
(20) Да, вовсю используются!
|
|||
23
smaharbA
18.08.10
✎
10:54
|
(21) спасибо за тестирование
было замечено, что кроме одной базы не ведут к такому эффекту, исследовать было лениво - от этого было выполнено (4) |
|||
24
Z1
18.08.10
✎
10:55
|
(17) смотри в той ветке пост 14 нет никакого перехвата.
+ к 14 надо добавить если Дата (как нач и конечная ) пустое значение то не включать это условие в sql запрос. работает на порядок быстрее чем ВыбратьПодчиненныеДокументы + нету нагрузки на sql сервер. |
|||
25
smaharbA
18.08.10
✎
10:55
|
||||
26
Dmitriy Kolyasnikov
18.08.10
✎
10:56
|
http://forum.windowsfaq.ru/showthread.php?t=104737
вот ссылка по теме, вроде человек решил проблему дефрагментацией индексов |
|||
27
smaharbA
18.08.10
✎
10:56
|
наверное выполню через АДО
|
|||
28
Dmitriy Kolyasnikov
18.08.10
✎
10:57
|
а тормоза действительно идут именно на этих операциях:
FETCH API_CURSOR0000000000000010 exec sp_cursorfetch 180150049,1,0,1 |
|||
29
Z1
18.08.10
✎
11:00
|
(25) где то год назад было обсуждение этого на форуме 1сpp.
Причина в том что запрос к sql "кривой" + база в формате 80 а это значит что оптимизатор запросов ( работает в режиме эмуляции ) не может это переварить. |
|||
30
smaharbA
18.08.10
✎
11:00
|
(29) в режиме 90 может ?
|
|||
31
Dmitriy Kolyasnikov
18.08.10
✎
11:06
|
база реиндексируется. как закончит - уберу везде где попадалось на тестах обращение к подчиненным документам (сервак-то пока тестовый, не жалко :) ), и отпишусь.
|
|||
32
Z1
18.08.10
✎
11:06
|
(30)для sql2008 штатный режим 100.
У меня нет sql2008. |
|||
33
Z1
18.08.10
✎
11:07
|
(26) про переиндексацию и.т.д
прочти ветку (особенно в конце ) http://www.1cpp.ru/forum/YaBB.pl?num=1275037619/0 |
|||
34
smaharbA
18.08.10
✎
11:07
|
(32) ну в режиме 100 есть вероятность что "переварит" ?
(о том что для адинес нужен 80 пока не думаем) |
|||
35
smaharbA
18.08.10
✎
11:34
|
как закладка ставится ?
|
|||
36
Z1
18.08.10
✎
12:13
|
(34) Вопрос из 34 как то непонятен. поясни вопрос.
|
|||
37
smaharbA
18.08.10
✎
12:18
|
(36) если поставить режим работы 100 (то что для адинес надо 80 - будем считать, что пропатчили так, что хавает любой) - то траблы не будет ?
И еще, а Док.ВыбратьДокументы() такие же проблемы вызывает ? |
|||
38
Dmitriy Kolyasnikov
18.08.10
✎
12:27
|
(11) Ихххааааа!!!!!
1. беру общий журнал, перебираю все вхождения ВыбратьПодчиненныеДокументы, и везде конструкцию ВыбратьПодчиненныеДокументы(,,Док.ТекущийДокумен()) меняю на ВыбратьПодчиненныеДокументы(Док.ДатаДок,Дата("31.12.37"),Док.ТекущийДокумент()). Пробую - работает! 2. тормоза при открытии реализации (она всегда проверяет свою СФ), закомментил поиск СФ - реализация стала открываться быстро! 3. заявка покупателя. У меня она при старте проверяет нет ли на её основании реализации, и плюсом проверяет наличие подчиненного документа "ДнфицитТовара". Переправил как в 1 - открывается сразу! итого - никаких АДО не надо чтобы запустить, работы на час если вдумчиво и с пивом :) Z1 спасибо огроменное!!!!! |
|||
39
Z1
18.08.10
✎
12:29
|
(37) не знаю. склрее всего да потому что запрос плохой.
Это легко проверить(если конечно есть на это желание и время). 1.Надо либо самому через профайлер ( либо уже есть в форумах тот запрос какой генкриться для подчиненных документов с пустой датой ) получить план этого запроса в базе формата 80. Перевести базу в формат 100 ( естественно что никто не должен в это время работать с базой) получить план этого запроса в базе формата 100. Перевести базу обратно в 80. Обновить статистики ососбенно по используемым индексам и Все тоже самое проделать. |
|||
40
1C-Nick
18.08.10
✎
12:31
|
(0) ответ в том, что 2005 и 2008 SQL при некотором стечении обстоятельств выбирают неправильный план выполнения запроса при поиске подчиненных документов.
в 2000 такой проблемы нет. Кроме того, зависит это всего лишь от параметров для этого запроса. решение - предлагать заменять план запроса На своей базе, взял параметры когда не тормозит и написал вот такой скрипт EXEC sp_create_plan_guide @name = N'_1SJOURN_Optimization', @stmt = N'Select JOURN.* from _1SJOURN JOURN(NOLOCK INDEX=ACDATETIME), _1SCRDOC CRDOC(NOLOCK INDEX=PARENT) where JOURN.DATE_TIME_IDDOC=CRDOC.CHILD_DATE_TIME_IDDOC and CRDOC.MDID=@P1 and CRDOC.PARENTVAL=@P2 and CRDOC.CHILD_DATE_TIME_IDDOC>=@P3 and CRDOC.CHILD_DATE_TIME_IDDOC<=@P4 order by CRDOC.MDID, CRDOC.PARENTVAL, CRDOC.CHILD_DATE_TIME_IDDOC', @type = N'SQL', @module_or_batch = NULL, @params = N'@P1 int,@P2 char(23),@P3 char(23),@P4 char(23)', @hints = N'OPTION(OPTIMIZE FOR (@P1 = 1824, @P2 = ''E1 W3 W4 '', @P3 = ''20090101 0 0 '', @P4 = ''20091231FHML6O 0 ''))'; |
|||
41
smaharbA
18.08.10
✎
12:33
|
(38) я уже то же колбашу по поводу пустот )))
Z1 - Огромное тебе Человеческое Спасибо ! самому было вломы думать - а есть еще те кто мыслит ))) |
|||
42
smaharbA
18.08.10
✎
12:35
|
(40) то же вариант, тока сильно "фиксированный"
|
|||
43
1C-Nick
18.08.10
✎
12:43
|
(42) почему фиксированный? просто план выполнения запроса оптимизируется для этих параметров, фактически же при выполнении подставляются правильные параметры
|
|||
44
Z1
18.08.10
✎
12:44
|
(38) >>>>итого - никаких АДО не надо чтобы запустить,
Я нигде не предлагал ADO ( прошлый век правда свой первый запрос написал именно на ADO но тогда даже Радуги не было). надо использовать 1срр. 1с++ использует родное соеденение с базой sql. Т.е. sql сервер не различает пришел запрос из встроенного языка 1с или это прямой запрос 1сpp Простой пример поясняющий суть. Предположим есть документ и у него 100 подчиненных документов Тогда если написать на 1с Док.ВыбратьПодчиненныеДокументы(Дата1,Дата2,КонкретныйДоукмент); Пока Док.ПолучитьДокумент() = 1 Цикл КонецЦикла; то на sql сервер уйдет как минимум 100 запросов на каждый полученный документ и один тот самый "не оптимальный" который получает все эти 100 итого имеем как минимум 101 sql запрос на sql сервере. Если написать на 1cpp на sql сервекр поступит и выполниться только ОДИН sql запрос. От этого выиграет как и конкретная сессия так и в целом общая нагрузка на sql сервер будет значительно ниже. |
|||
45
Vladal
18.08.10
✎
12:44
|
А какие внешние компоненты используются?
Может оно и висит, пока админ не зайдёт и не запустится компонента? |
|||
46
1C-Nick
18.08.10
✎
12:46
|
(45) оно висит потому что не 2000 SQL Server
|
|||
47
smaharbA
18.08.10
✎
12:46
|
(45) не попал
(44) про АДО моя сказал, ибо нет 1с++ или на случай отсутствия таковой |
|||
48
Z1
18.08.10
✎
12:46
|
(43) когда нет конечной даты нет то
@P4 = ''99991230 !!! Вот от такого параметра и начинается колбаситься sql сервер пытвется найти оптимальный план и.т.д. и.т.п. |
|||
49
smaharbA
18.08.10
✎
12:50
|
думаю как оставить такую конструкцию (может кто наведет на мысли)
|
|||
50
smaharbA
18.08.10
✎
12:51
|
+(49) без родного Док.ВыбратьПодчиненныеДокументы в глВыбратьПодчиненныеДокументы
|
|||
51
1C-Nick
18.08.10
✎
12:55
|
(48) да, но вместо того чтобы менять конфигурацию, как по мне проще один раз создать plan guide
|
|||
52
Dmitriy Kolyasnikov
18.08.10
✎
12:56
|
(44) согласен, просто времени особо нет сейчас на это. правка родного запроса дала вполне адекватный результат в работе.
(40) получается, этот скрипт нужно просто выполнять после каждого обновления конфы? |
|||
53
1C-Nick
18.08.10
✎
13:05
|
(52) и после обновления конфы не надо. один раз для загруженной базы
|
|||
54
Oleg_Kag
18.08.10
✎
13:16
|
блин, в базу знаний кто-нибудь добавьте. ау! модераторы!
|
|||
55
Dmitriy Kolyasnikov
18.08.10
✎
13:19
|
(53) этот скрипт для 2005 используется?
Сообщение 1018, уровень 15, состояние 1, строка 1 Неправильный синтаксис около "INDEX". Если имелась в виду часть табличной подсказки, то для этого теперь необходимо использовать ключевое слово A WITH и круглые скобки. Правильный синтаксис см. в электронной документации по SQL Server. Сообщение 10516, уровень 16, состояние 1, процедура sp_create_plan_guide, строка 20 Невозможно создать структуру плана "_1SJOURN_Optimization", так как не удалось скомпилировать @module_or_batch. |
|||
56
sapphire
18.08.10
✎
13:32
|
Совместимость с SQL 2k у БД указал?
|
|||
57
Dmitriy Kolyasnikov
18.08.10
✎
13:48
|
(56) да
|
|||
58
1C-Nick
18.08.10
✎
15:30
|
(55) да, для 2005.
видимо ему не нравится JOURN(NOLOCK INDEX=ACDATETIME) надо типа JOURN WITH (NOLOCK INDEX=ACDATETIME) Но вопрос в другом: как же тогда 1С запросы работают, ведь там нет этого ключевого слова... |
|||
59
1C-Nick
18.08.10
✎
15:31
|
в профайлере интересно какой запрос идет...
|
|||
60
smaharbA
18.08.10
✎
15:36
|
скорее всего когда запрос из манагера он подразумевается как родной, а когда при подключении "со стороны" тогда и работает эта совместимость
|
|||
61
smaharbA
18.08.10
✎
15:36
|
+(60) чиста догадки даже не на кофейной гуще
|
|||
62
1C-Nick
18.08.10
✎
15:52
|
(60) по идее нет, может быть просто процедура sp_create_plan_guide таким образом запрос разбирает. Но у меня нет под рукой 2008 чтобы проверить.
Ждем автора... |
|||
63
Z1
18.08.10
✎
16:05
|
(58)
>>>Но вопрос в другом: как же тогда 1С запросы работают, ведь там нет этого ключевого слова... База 1с для sql2008(sql2005) работают в формате 80. Для формата 80 - язык t-sql sql2000 а в нем with является необязательным и with никодга не выставляется из 1с Также оптимизатор запросов Может посчитать запрос с with и без with как разные запросы и снова получим subj. |
|||
64
1C-Nick
18.08.10
✎
16:42
|
(63) если там формат 80, почему же ошибка возникла в (55) - вот что странно
|
|||
65
Dmitriy Kolyasnikov
18.08.10
✎
16:49
|
(62) а что будем попробовать? запустить скрипт с "JOURN WITH" под 2008 SQL, и когда он его примет проверить опознает ли скуль запрос из 1С по нашей маске?
база 80 формата |
|||
66
Dmitriy Kolyasnikov
18.08.10
✎
16:53
|
+(62) добавил 2 with - скрипт отработал, обращения к подчиненным журналам виснут.
видимо (60) = true :-D |
|||
67
leshikkam
18.08.10
✎
16:55
|
Простите пожалуйста - а никто не подскажет с чем связано ограничение на режим совместимости базы с 2000 SQL и почему нельзя запускать в режиме 2005 (9.0)?
|
|||
68
Dmitriy Kolyasnikov
18.08.10
✎
16:58
|
ну вот видимо потому и нельзя, что на запросы 1С SQL будет отвечать через раз "синтаксис эррор" :)
|
|||
69
Dmitriy Kolyasnikov
18.08.10
✎
17:05
|
а скрипт (40) нельзя как-то модифицировать с подменой по типу ВК romix-а, типа получил запрос без With - выполняй с with, параметры вот такие?
|
|||
70
Z1
18.08.10
✎
17:16
|
(66) смотри 63
|
|||
71
1C-Nick
18.08.10
✎
17:33
|
(69) профайлером отлови текст запроса когда подчиненный документ открываешь - какой он?
|
|||
72
Z1
18.08.10
✎
17:33
|
(67) смотри пример
если база в формате 80 ( sql2005,sql2008) то можно написать так Вариант 1 JOURN WITH (NOLOCK INDEX=ACDATETIME) а можно так Вариант 2 JOURN (NOLOCK INDEX=ACDATETIME) 1c.exe генерит всегда без witj если база в формате 90 ( sql2005,sql2008) то вариант 2 Неприемлим (только Вариант 1 )когда опций больше одной и это есть синтаксическая ощибка запроса. А значит запрос не выполниться. Как правило 1с.exe на таких ошибках происходит вылет программы. также насколько помню 90,100 для списка with Желательно в качестве разделителя опций использовать не пробел а запятую т.е вместо WITH (NOLOCK INDEX=ACDATETIME) более граммотно надо писать так : WITH (NOLOCK,INDEX=ACDATETIME) |
|||
73
Z1
18.08.10
✎
17:36
|
(69) распиши подробней. не совсем понятно что ты хочешь сделать.
но вроде нельзя т.к. этот запрос используется при итерактивном журнале и в курсооах а курсор ты не перехватишь. |
|||
74
1C-Nick
18.08.10
✎
18:19
|
(69) а текущая база выбрана 1С или master при выполнении запроса?
|
|||
75
Dmitriy Kolyasnikov
19.08.10
✎
09:00
|
(74) 1C
(71) такой же как у всех запрос :) отловил: Select JOURN.* from _1SJOURN JOURN(NOLOCK INDEX=ACDATETIME), _1SCRDOC CRDOC(NOLOCK INDEX=PARENT) where JOURN.DATE_TIME_IDDOC=CRDOC.CHILD_DATE_TIME_IDDOC and CRDOC.MDID=@P1 and CRDOC.PARENTVAL=@P2 and CRDOC.CHILD_DATE_TIME_IDDOC>=@P3 and CRDOC.CHILD_DATE_TIME_IDDOC<=@P4 order by CRDOC.MDID, CRDOC.PARENTVAL, CRDOC.CHILD_DATE_TIME_IDDOC кстати я его еще блокнотом нашел в bkend.dll :-D можно наверное там добавить with :-D (69) что хочу сделать - заставить SQL получать запрос с with чтобы сработал план оптимизации. А как этот план увидеть в самом SQL? где он там? запросами вижу, что он есть, а в меню найти не могу. |
|||
76
Dmitriy Kolyasnikov
19.08.10
✎
09:00
|
тьфу, к (73) последний ответ, я (69) поставил
|
|||
77
DrZombi
гуру
19.08.10
✎
09:10
|
Ну как успехи ?
Смогли победить не совместимость платформы 7.7 со SQL 2005 и 2008 + т.д. последующие версии продукта :) ? |
|||
78
Dmitriy Kolyasnikov
19.08.10
✎
09:25
|
+(71) а HEX-редактором не нашел запрос в dll... ну может оно и к лучшему, тему не закроют :-D
|
|||
79
Dmitriy Kolyasnikov
19.08.10
✎
09:25
|
да что такое :) к (75) хотел добавить
|
|||
80
Z1
19.08.10
✎
09:25
|
(75) with Вам не поможет
все дело в @P4. когда нет конечной даты запрос должен выглядеть так Select JOURN.* from _1SJOURN JOURN WITH(NOLOCK INDEX=ACDATETIME), _1SCRDOC CRDOC(NOLOCK INDEX=PARENT) where JOURN.DATE_TIME_IDDOC=CRDOC.CHILD_DATE_TIME_IDDOC and CRDOC.MDID=@P1 and CRDOC.PARENTVAL=@P2 and CRDOC.CHILD_DATE_TIME_IDDOC>=@P3 order by CRDOC.MDID, CRDOC.PARENTVAL, CRDOC.CHILD_DATE_TIME_IDDOC Когда нет ни начальной даты ни конечной так Select JOURN.* from _1SJOURN JOURN WITH(NOLOCK INDEX=ACDATETIME), _1SCRDOC CRDOC(NOLOCK INDEX=PARENT) where JOURN.DATE_TIME_IDDOC=CRDOC.CHILD_DATE_TIME_IDDOC and CRDOC.MDID=@P1 and CRDOC.PARENTVAL=@P2 order by CRDOC.MDID, CRDOC.PARENTVAL, CRDOC.CHILD_DATE_TIME_IDDOC Далее использование для внутреннего соедениния старого стиля никак не способствует составлению оптимального плана выполнения (рекомендация MS использовать INNER JOIN ) (75) Вы как то не последовательны то хотите горы свернуть переписать bkend.dll , использовать перехватчик запросов и все это с неизвестным результатом с другой стороны когда Вам предлагают готовое работающее решение в виде 1сpp то на его изучение у Вас нет времени. |
|||
81
Z1
19.08.10
✎
09:38
|
(77) О какой несовместимости речь ?
Конкретно запрос обсужаемый в теме "корявый" для любой версии sql сервера. то что sql2000 как-то с этим запросом справляется а sql2005, sql2008 нет, это не значит что есть несовместимость (запрос плох и для sql2000) а на мой взгляд означает что есть "плохой" t-sql запрос можно считать это фичей 1с приложения. Другое дело что 1с ни признают это ошибкой ни тем более не будут это исправлять. |
|||
82
Dmitriy Kolyasnikov
19.08.10
✎
09:56
|
(80) возможно я увлекся, учту критику.
с другой стороны, рассуждения "Предположим есть документ и у него 100 подчиненных документов" считаю своего рода спекуляцией :) у меня очень редко когда бывает больше 4х подчиненных документов, кол-во таких длинных деревьев из документов не превысит 3% от общего числа, и в этих 3% там кол-во документов в пределах 10. |
|||
83
Z1
19.08.10
✎
10:21
|
(82) в 44 число 100 было выбрано специально чтобы более ощутимо можно было увидеть преимущество 1сpp.
Хорошо если есть четыре подчененных документа у конкретного документа то выполнение одного sqlзапроса вместо как минимум 5 sql запросов это большой выигрыш ( тем более этот единственный запрос лишен недостатка по границе дат). Если говорить о деревьях ( И если у тебя нет какой-то супер специфики) то на 1cpp где-то есть обработка (автор orefkov) получает все дерево подчинения одним sql запросом. |
|||
84
Z1
19.08.10
✎
11:26
|
Вот еще ссылка разъясняющая полностью subj
http://www.sql.ru/Forum/actualthread.aspx?tid=714878&pg=1&mid=7977072 и цитата от туда же : "Я хочу сказать, что запросы нужно оптимальные писать. А просто любые" Glory |
|||
85
1C-Nick
19.08.10
✎
11:43
|
(84) в коллекцию http://www.sql.ru/Forum/actualthread.aspx?bid=1&tid=605678&hl=journ
|
|||
86
smaharbA
19.08.10
✎
14:56
|
(84) не прав Glory - пусть скульщики заядные понапишут стока запросов скока в адинес реализовано - они просто сдохнут, конечно когда таблицы и т.д. чуть ли не руками выстроены говорить о "правильных" запросах просто, ибо их будет с десятка полтора, а вот когда таблицы и потребности могут быть различны - тут тока базары или адинес/сап и т.п.
|
|||
87
Ковычки
19.08.10
✎
15:09
|
Ветку в Бздню, отмечать не понятно как и что, но попытаю
и верните ИЗ, а стукача повешать ! |
|||
88
Dmitriy Kolyasnikov
20.08.10
✎
15:43
|
новости с полей :)
без 1с++ никак не обойтись! И дело не в количестве подчиненных документов, а в отборе по датам. Сравнивал: выборка подчиненных документов на 1с++ выборка подчиненных с указанием интервала (Док.ДатаДок, Дата("31.12.37")... выборка подчиненных с указанием интервала (Дата ("01.01.06"), Дата("31.12.37")... выборка подчиненных с пустыми датами первый вариант и второй при работе с документами в конце журнала (по дате) глазом разницу не видно, но будем считать что она есть :) третий вариант по скорости близок к последнему (подозреваю, что все 1,7 млн документов проверяются по дате попадают ли они в выборку). Но второй вариант вырождается в третий при работе с достаточно старыми документами! |
|||
89
Dmitriy Kolyasnikov
20.08.10
✎
16:48
|
В ссылке из (11) написано, что 1с++ в общих журналах не решает проблему - частично подтверждаю, на 2000 SQL общий журнал работает быстрее, но не на порядки, а в разы. Т.е. в принципе работать теперь вполне можно.
осталось переписать оставшиеся 94 вызова ВыбратьПодчиненныеДокументы в эмдэшнике и отловить и переписать все их во внешних отчетах :) |
|||
90
Cthulhu
20.08.10
✎
17:04
|
(89): подозреваю что ступлю но все-тки спрошу. а что, в 1с++ не получится слепить какой-нито класс "подчиненныедокументы" чтобы только "создатьобъект" поменять понадобилось в коде (методы "выбратьподчиненныедокументы", "получитьдокумент" чтобы были с таким же синтаксисом)?..
ЗЫ: ну или гуру попросить нарисовать ВК которая реализует объект подчиненного документа с быстрыми выпорками?.. |
|||
91
Dmitriy Kolyasnikov
23.08.10
✎
10:10
|
(90) просить гуру - не наш метод :)
В общем за каких-нибудь 10-12 часов я всё переписал, уже запустился на новом серваке. Сейчас в базе 84 пользователя, всё работает. в половине случаев или даже больше вместо выбора подчиненных я использовал следующую функцию: //возвращает первый найденный документ указанного вида, подчиненный ДокРодитель //если не нашел, то возвращает пустое значение Функция глПолучитьПервыйПодчиненныйПоВиду(ДокРодитель, ПоВиду, ТолькоПроведенные = 0, ТолькоНеПомеченные = 1) Экспорт СкульЗапрос=" |SELECT top 1 | TabJ.IDDOC, | TabJ.IDDOCDEF |FROM | _1SCRDOC As TabRod(NOLOCK) |INNER JOIN | _1SJOURN As TabJ(NOLOCK) ON (TabRod.CHILDID = TabJ.IDDOC) |WHERE | TabRod.MDID = 0 -- только документы, без граф отбора | AND TabRod.PARENTVAL = '"+глМД.ЗначениеВСамуюДлиннуюСтрокуБД(ДокРодитель.ТекущийДокумент())+"' | And IDDOCDEF='"+глМД.ИДДокумента(ПоВиду)+"'"; Если ТолькоПроведенные = 1 Тогда СкульЗапрос=СкульЗапрос+" |and CLOSED=1"; КонецЕсли; Если ТолькоНеПомеченные = 1 Тогда СкульЗапрос=СкульЗапрос+" |and ISMARK=0"; КонецЕсли; тзДок = глЗапрос.ВыполнитьИнструкцию(СкульЗапрос); Если тзДок.КоличествоСтрок() > 0 Тогда тзДок.ПолучитьСтрокуПоНомеру(1); Возврат глМД.ЗначениеИзСтрокиБД(12,тзДок.IDDOCDEF,тзДок.IDDOC); Иначе Возврат ПолучитьПустоеЗначение("Документ."+ПоВиду); КонецЕсли; КонецФункции |
|||
92
Ёпрст
23.08.10
✎
10:15
|
(91) CLOSED=1 не всегда =1 у проведенных документов, всё зависит от набора компонент.
|
|||
93
Ёпрст
23.08.10
✎
10:16
|
+92 нафига делать глМД.ЗначениеИзСтрокиБД ? когда проще в самом запросе типизировать?
|
|||
94
Dmitriy Kolyasnikov
23.08.10
✎
10:26
|
(92) да! спасибо! исправлю на >0
(93) подскажите пожалуйста как это сделать, я использовал готовый код (переписывал), там было использовано ЗначениеИзСтрокиБД. |
|||
95
Ёпрст
23.08.10
✎
10:30
|
(94)
TabJ.IDDOC [Док $Документ] |
|||
96
Dmitriy Kolyasnikov
23.08.10
✎
10:32
|
(95) спасибо! попробую и такой вариант.
|
|||
97
smaharbA
23.08.10
✎
16:07
|
хочу конструкцию
Док.ВыбратьПодчиненныеДокументы и т.д |
|||
98
Ёпрст
23.08.10
✎
17:35
|
(97) оберни в класс
|
|||
99
smaharbA
24.08.10
✎
09:59
|
Сделал тупо, и странно дело - загрузки под завязку не наблюдаю уже с 19 числа...
(думаю о 1с++ и Классе)
|
|||
100
Dmitriy Kolyasnikov
01.09.10
✎
13:09
|
я всё переписал на прямых запросах, но тормоза иногда начинаются все равно :(
Начинаются ТОЛЬКО в общих журналах, т.е. они шлют тот же самый корявый запрос, хотя в коде модуля его нет! длл-ку перехвата запросов от romix-а не могу запустить, пишет access violation, как я понял из обсуждений, она не дружит с 1с++. чего делать - хз :( |
|||
101
МихаилМ
01.09.10
✎
13:46
|
то(100)
подмените таблицу отборов на представление еще лучше секционируйте представление. использоать представления можно используя патчи 1с77 либо подправив sp_tables |
|||
102
Ковычки
01.09.10
✎
22:36
|
(100) замечено, что на прямом запросе медленнее отрабатывает и сильнее загружает, чем как в (99) и далее ПолучитьДокумент()... Немного дело поправляет параметрический запрос не закрывающийся
|
|||
103
Ковычки
01.09.10
✎
22:38
|
+(102) речь о наличии в текстовом поле многострочной части журнала на подбее
АЕстьЛиПодчиненныеПроведенныеИТакихТоВидов |
|||
104
Dmitriy Kolyasnikov
02.09.10
✎
07:24
|
(102) выборка через ВыбратьПодчиненныеДокументы() с указанным периодом дат работает очень медленно, когда в период, заключенный между датами, попадает достаточно много документов (у меня 1,7 млн от первого до последнего) и документ, которому ищем подчиненные, стоит в начале журнала. Если в базе тысяч 300 доков, то можно не париться и делать как в (99).
прямыми запросами все отлично и очень быстро работает в любом периоде в отчетах, документах, и на любых журналах кроме общих, в общих Ж. через раз :( |
|||
105
smaharbA
02.09.10
✎
07:49
|
(104) в (102) о ситуации в журнале - на многострочной части висит текстовое поле с формулой
ВПланахДокумент(ТекущийДокумент) Функция ВПланахДокумент(Док="") Перем Сп; Если ПустоеЗначение(Док)=1 Тогда Возврат 0; КонецЕсли; Если (Док.Вид()="ЗаказНаОтгрузку") Тогда Если Константа.ИспользоватьПрямыеЗапросы=Да Тогда Сп=СоздатьОбъект("СписокЗначений"); Сп.ДобавитьЗначение("ПланПроизводства"); Если глДокументСписокПодчиненныхSQL(Док.ТекущийДокумент(),2,Сп,,,глСоединение,1,Подготовить)>0 Тогда Возврат 2; КонецЕсли; Иначе ДокПодч=СоздатьОбъект("Документ"); глВыбратьПодчиненныеДокументы(ДокПодч,,,Док.ТекущийДокумент()); ДокПодч.УстановитьФильтр(1,0); Пока ДокПодч.ПолучитьДокумент()=1 Цикл Если ДокПодч.Вид()="ПланПроизводства" Тогда Возврат 2; КонецЕсли; КонецЦикла; КонецЕсли; КонецЕсли; Возврат 0; КонецФункции // ВПланахДокумент |
|||
106
smaharbA
02.09.10
✎
07:51
|
+(105) даже параметрический запрос единожды подготовленный отрабатывает медленнее чем выборка с указанием диапазона
|
|||
107
Dmitriy Kolyasnikov
02.09.10
✎
08:34
|
(106) ладно, на вкус и цвет :) быстрее работает выборка с указанием диапазона - значит надо использовать её. У меня она работала очень плохо в начале журнала из 1,7 млн документов, как раз в текстовых полях журнала и были вызовы. После тестов я переписал всё на прямых запросах.
У меня еще прикол нашелся. Когда пользователи переходят в журнал подчиненных документов - там видимо тем же самым корявым запросом выбираются подчиненные без указания дат, виснет намертво так, что даже кнопку "закрыть" удается раза с 10-го нажать. Ночью сегодня снесу журнал подчиненных, пусть пользуются "структурой подчиненности". |
|||
108
smaharbA
02.09.10
✎
08:36
|
(107) это когда один пользователь в наличии ?
|
|||
109
Dmitriy Kolyasnikov
02.09.10
✎
08:39
|
(108) если вопрос по первой части (106) - то да, тесты делал когда в базе было 2-4 юзера.
если вопрос по журналу подчиненных - то нет, в базе 80 пользователей сидят, из них подчиненными пользовался один отдел, человек 10. |
|||
110
smaharbA
02.09.10
✎
08:40
|
(109) а журнал присутствует в конфигурации ?
|
|||
111
Dmitriy Kolyasnikov
02.09.10
✎
08:41
|
(110) в общем журнале стоит галка "использовать как журнал подчиненных документов"
|
|||
112
smaharbA
02.09.10
✎
08:41
|
(107) а текстовое поле на форме или колонка в многострочной ?
|
|||
113
Dmitriy Kolyasnikov
02.09.10
✎
08:44
|
(112) колонка в многострочной
|
|||
114
smaharbA
02.09.10
✎
08:53
|
(113) ясно, а можно как пример позырить прямой запрос который используется на этой колонке ?
|
|||
115
smaharbA
02.09.10
✎
09:09
|
мой типа такого (запрос взял родной адинесовский пока, и все эти idtostr и значениеизстрокивнутр - ибо будет АДО, а не 1с++, 1с++ - сравнивал с адо, прироста производительности не заметил)
|
|||
116
Dmitriy Kolyasnikov
02.09.10
✎
09:17
|
(114) посмотрел - идут вызовы и в многострочной части, и в строке на форме.
В многострочной части ВернутьСтатус(), дальше как я проверяю наличие Реализации, дальше вызов в строке на форме (функция на скуле к этому вызову уже показана выше) //---------------------------------------------- Функция ВернутьСтатус(Док) Если Док.Выбран()=0 Тогда Возврат ""; КонецЕсли; ДокВид = Док.Вид(); Если ДокВид = "ЗаявкаПокупателя" Тогда Если глФлагРНК(ТекущийДокумент) = 1 Тогда Возврат "Полностью"; Иначе Если МанхРаботает = 1 Тогда Возврат ПроверитьСтатусМанх(); КонецЕсли; КонецЕсли; ... //---------------------------------------------- //возвращает 1 если есть РНК, возвращает 0 - если нет //По умолчанию показывает только при проведенных РНК Функция глФлагРНК(ДокЗаявка, ТолькоПроведенные = 1) Экспорт Если ДокЗаявка.Выбран() = 0 Тогда Возврат 0; КонецЕсли; СкульЗапрос=" |SELECT | TabJ.IDDOC |FROM | _1SCRDOC As TabRod(NOLOCK) |INNER JOIN | _1SJOURN As TabJ(NOLOCK) ON (TabRod.CHILDID = TabJ.IDDOC) |WHERE | TabRod.MDID = 0 -- только документы, без граф отбора | AND TabRod.PARENTVAL = '"+глМД.ЗначениеВСамуюДлиннуюСтрокуБД(ДокЗаявка.ТекущийДокумент())+"' | And IDDOCDEF='"+глМД.ИДДокумента("Реализация")+"'"; Если ТолькоПроведенные = 1 Тогда СкульЗапрос=СкульЗапрос+" |and CLOSED>0 |"; КонецЕсли; тзРеализации = глЗапрос.ВыполнитьИнструкцию(СкульЗапрос); Если тзРеализации.КоличествоСтрок() > 0 Тогда Возврат 1; Иначе Возврат 0; КонецЕсли; КонецФункции //---------------------------------------------- на форме: //---------------------------------------------- ДокПодч = глПолучитьПервыйПодчиненныйПоВиду(ТекущийДокумент.ТекущийДокумент(),"ДефицитТовара"); Если ПустоеЗначение(ДокПодч) = 0 Тогда ДокДефицитНайден = 1; ДокДефицит.НайтиДокумент(ДокПодч); КонецЕсли; Если ДокДефицитНайден = 0 Тогда Возврат ""; Иначе СуммаДефицита = ДокДефицит.СуммаВзаиморасчетов; темп = "2/"; Если СуммаДефицита = 0 Тогда ДокДефицит.ВыбратьСтроки(); Пока ДокДефицит.ПолучитьСтроку() = 1 Цикл СуммаДефицита=СуммаДефицита+ДокДефицит.Сумма; КонецЦикла; КонецЕсли; Возврат ("Дефицит товара "+ДокДефицит.НомерДок+" : "+СОКРЛП(Формат(СуммаДефицита,"Ч12.2"))+" р."); КонецЕсли; //---------------------------------------------- |
|||
117
Dmitriy Kolyasnikov
02.09.10
✎
09:22
|
(115) я отказался от дат. Во всей конфе в 90 вызовах ВыбратьПодчиненные даты реально нужны были в одном документе, который у меня не используется :)
|
|||
118
Dmitriy Kolyasnikov
02.09.10
✎
09:26
|
+(117) тем более если в качестве первой и последней даты использовать позицию первого и последнего документа или вообще любой достаточно большой интервал - то проще его не контролировать совсем. Проще и скулю и нам :)
|
|||
119
Ленинград
02.09.10
✎
09:39
|
закладочко
|
|||
120
smaharbA
02.09.10
✎
09:47
|
(116) параметрический запрос быстрее будет, у меня при первом обращении идет подготовка и выполнение, при последующих только смена параметров (установка) и выполнение, закрытие не делается
|
|||
121
Z1
02.09.10
✎
09:53
|
(107)
>>>У меня еще прикол нашелся. Когда пользователи переходят в журнал подчиненных ? >>>документов - там видимо тем же самым корявым запросом выбираются подчиненные без указания дат, >>>виснет намертво так, что даже кнопку "закрыть" удается раза с 10-го нажать. При открытии журнала подчиненных документов установи интервал журнала.Сам так не делал но должно српаботать. Второе решение при открытии журнала подчиненных документов, сам журнал закрывай и открывай свою форму отчета с ТП где отображаются подчиненные документы. |
|||
122
Dmitriy Kolyasnikov
02.09.10
✎
09:58
|
(120) про параметрический - возможно, но проверка дат - считаю это лишняя работа для скуля.
(121) т.е. мое решение - убрать подчиненный журнал вообще - будет иметь какие-то негативные последствия? |
|||
123
smaharbA
02.09.10
✎
10:02
|
вопрос знатокам
использование в запросе конструкции exec ('текст запроса') сильно снизит производительность ? |
|||
124
Z1
02.09.10
✎
10:03
|
(105, 115 )
>>>а не 1с++, 1с++ - сравнивал с адо, прироста производительности не заметил) Преимуществ у 1сp по сравнению с ado очень много например : 1.1сpp работает в подном соеденении. т.е если у тебя 50 пользователей то 50 лишних конектов это ресурсы sql сервера. если все время открывать и закрывать ado конект то это очень трудоемкая операция 2. 1сpp дает типизацию объектов а ado нет. Делая типизацию чем либо внутри 1с по скорости сведешь на нет все преимущества sql запроса. 3. ado выдает записи по одной а в 1cpp получаем сразу ТаблицуЗначений (заполнение ТЗ идет не на языке 1с а на языке С внутри 1сpp ) |
|||
125
smaharbA
02.09.10
✎
10:04
|
(124) пункты 2. и 3. как бы мене не критичны, а вот п 1. это да
|
|||
126
Z1
02.09.10
✎
10:14
|
(116)
вместо Если ДокЗаявка.Выбран() = 0 Тогда надо обязательно писать Если ПустоеЗНачение(ДокЗаявка) = 1 Тогда В текст запроса можешь поставить top 1 параметризацию документа надо делать через 1сpp УстановитьТекстовыйПараметр вместо глМД.ИДДокумента("Реализация") пиши конкретное число оно же у тебя вообще не меняется либо через 1сзз $ВидДокумента.Реализация ( синтаксис точно не помню ) |
|||
127
Z1
02.09.10
✎
10:18
|
(123) Вопрос вообще не понятен
о чем идет речь ? |
|||
128
Dmitriy Kolyasnikov
02.09.10
✎
10:19
|
(126)
>вместо >Если ДокЗаявка.Выбран() = 0 Тогда >надо обязательно писать >Если ПустоеЗНачение(ДокЗаявка) = 1 Тогда почему так? использую Выбран() = 0, т.к. эта функция используется в форме заявки, в т.ч. пока она не была записана. Ну и как я помню ПустоеЗначение(ДокЗаявка) = 1, если ДокЗаявка - это документ, а не ссылка .ТекущийДокумент() ... |
|||
129
Z1
02.09.10
✎
10:21
|
(122)
>>> т.е. мое решение - убрать подчиненный журнал вообще - будет иметь какие-то >>> негативные последствия? Последсвий не будет. Через отчет тоже все наглядно. Если только чисто психологически пользователи к чему либо другому болезнено привыкают. Второе решение - вместо журнала подчиненных - Используй ТП на своей форме |
|||
130
Z1
02.09.10
✎
10:25
|
ДокЗаявка.Выбран() генерит запрос к базе к _1journ ( если объект не в кеше 1с)
ПустоеЗНачение проверяет IDDOC на ' 0 ' ( даже на этом форуме поищи есть ветка этоко года orefkov это объяснял в деталях ) |
|||
131
smaharbA
02.09.10
✎
11:02
|
(127) есть необходимость менять направление сортировки для получения top (x)
как это сделать в параметризированном запросе не знаю, вот и думал вызвать типа ТекстЗапроса="exec ('select top asc('+?+') * from ... order by ...'+?)"; |
|||
132
Z1
02.09.10
✎
12:31
|
(131) На мой взгляд никак. Параметр сортировки не может быть
параметризирован на уровне sql ( точно также как и имя таблицы ) т.е. на 1с должно быть что-то типа( заранее говорю что sql2005, sql2008 знаю очень плохо может в чем то уже и не прав ) Если Прямой_порядок_сортировки() = 1 Тогда ТекстрЗапроса = 'select top ('+?+') * from ... order by X1')"; иначе ТекстрЗапроса = 'select top ('+?+') * from ... order by X1 dec')"; КонецЕсли; |
|||
133
smaharbA
02.09.10
✎
12:43
|
(132) вот в том и дело, по этой причине и хочу в запросе использовать exec, но не в курсе на сколько это тормознее чем просто выполнение запроса
|
|||
134
Z1
02.09.10
✎
13:02
|
(133) не выиграешь ну и не проиграешь.
насколько я помню exec идет к sql meneger а твой запрос и так к нему попадет. |
|||
135
Dmitriy Kolyasnikov
02.09.10
✎
17:03
|
(120)(126) Помогите пожалуйста понять выигрыш от параметризации на реальной задаче. У документов "Реализация" есть подчиненные "ФакторингФинансирование". В этих документах в табличной части 2 поля: Реализация("Документ.Реализация"), и Сумма (число).
Дано: ссылка на реализацию (.ТекущийДокумент()) Найти: сумму финансирования из документа ФакторингФинансирование запрос сразу работает по подчиненным документам: скульзапрос = " |SELECT | $ДокФ.Сумма as СуммаФинансирования |FROM | $ДокументСтроки.ФакторингФинансирование as ДокФ |INNER JOIN | _1SCRDOC as ЖурПодч ON (ЖурПодч.CHILDID = ДокФ.IDDOC | AND ЖурПодч.PARENTVAL = :ИДРеализации) |WHERE $ДокФ.Реализация = :ИДРеализации9 |"; глЗапрос.УстановитьТекстовыйПараметр("ИДРеализации",глМД.ЗначениеВСамуюДлиннуюСтрокуБД(ВыбДок.ТекущийДокумент())); глЗапрос.УстановитьТекстовыйПараметр("ИДРеализации9",глМД.ЗначениеВСтрокуБД(ВыбДок.ТекущийДокумент())); рез = глЗапрос.ВыполнитьИнструкцию(скульзапрос); Если рез.КоличествоСтрок() > 0 тогда рез.ВыбратьСтроки(); рез.ПолучитьСтроку(); Сообщить(рез.СуммаФинансирования); Иначе Сообщить("документ не профинансирован"); КонецЕсли; |
|||
136
Dmitriy Kolyasnikov
02.09.10
✎
17:06
|
+(135) запрос рабочий, показывает верные данные.
И вот как я тут выигрываю по сравнению с тем, если бы вставил текст прямо в запрос? Я же в любом случае каждый раз передаю "скульзапрос" в ВыполнитьИнструкцию? Я примерно понимаю в чем разница, но гештальт не складывается :) запрос привязываю к расшифровке ячейки в печатной форме отчета. |
|||
137
Z1
02.09.10
✎
18:26
|
(135) Давай сначала поправь свой запрос так :
скульзапрос = " |SELECT | $ДокФ.Сумма as СуммаФинансирования |FROM | $ДокументСтроки.ФакторингФинансирование as ДокФ |INNER JOIN | _1SCRDOC as ЖурПодч ON (ЖурПодч.CHILDID = ДокФ.IDDOC | AND ЖурПодч.PARENTVAL = :ИДРеализации* |WHERE $ДокФ.Реализация = :ИДРеализации |"; глЗапрос.УстановитьТекстовыйПараметр("ИДРеализации",ВыбДок); |
|||
138
Z1
02.09.10
✎
18:30
|
(136) Выигрыш от одиночного запроса никакого не получишь.
Тут как бы речь идет о том что велика вероятность что через небольшое время придет аналогичный запрос и вот тут то параметр дает выигрыш в том что план выполнения отработанного запроса выполняется из буфера выполнения не сразу а через какое-то время и поэтому выполнение аналогичного запроса будет значительно быстрее. |
|||
139
Z1
02.09.10
✎
18:45
|
Продолжим в этом посте то что sql запросы я пишу с точки зрения sql сервера
предположим есть два запроса запрос1 select * from _1sjourn where iddoc = '123456' запрос2 select * from _1sjourn where iddoc = '123457' Для sql сервера это два абсолютно разных запроса и для каждого из них будет независимо составляться свой план выполнения и после этого этот план будет выполняться. Т.е. происходит компиляция запроса его выполнения.В кеше запросов будет очень много почти идентичных запросов ( с очень низкой ценностью). Чтобы этого избежать были придуманы параметризированные запросы ( начиная с sql 7.0 ) т.е. на sql сервер должен попасть запрос select * from _1sjourn where iddoc = ? После получения такого запроса происходит его компиляция. И план запроса помещается в кеш. Для выполнения такого запроса на сервер надо передать только параметр сначала '123456' потом '123457' В кеше запросов имеет только один план выполнения и ценность такого плана очень большая и он будет долго в кеше. При этом выигрыш имеем в том что используется уже созданный план запроса второй выигрыш кеш запросов используется на порядок оптимальней а значит другие паралельно работающие запросы в среднем выполняются быстрее. |
|||
140
Z1
02.09.10
✎
18:57
|
чтобы использовать в 1сpp параметризированные запросы есть два способа
1 способ надо включить РежимRPC и обязательно использовать УстановитьТекстовыйПараметр. Тогда установленые параметры превращаются в параметры sql запроса ( те самые ? ) пояснение : Запрос = СоздатьОбъект("ODBCRecordSet"); Запрос.РежимRPC(1); Запрос.УстановитьТекстовыйПараметр("НачДата", ДатаНач); 2 способ Использовать напрямую параметры sql Пример посмотри хотя бы здесь http://www.1cpp.ru/forum/YaBB.pl?num=1283238589 Способ два конечно быстрее но в нем гораздо больше способов где можно ошибиться, (особено с правильностью указания типов) на мой взгляд его тяжело использовать и выигрыш по сравнению с первым способом будет небольшой. Т.е мое мнение способ 2 надо применять где нужна еще большая производительность чем способ1. |
|||
141
Z1
02.09.10
✎
19:04
|
В 138 опечатка ( т.к. редактировать посты нельзя то напишу заново )
правильный 138 : Выигрыш от одиночного запроса никакого не получишь. Тут как бы речь идет о том что велика вероятность что через небольшое время придет аналогичный запрос и вот тут то параметр дает выигрыш в том что план выполнения отработанного запроса УДАЛЯЕТСЯ из буфера выполнения не сразу а через какое-то время и поэтому выполнение аналогичного запроса будет значительно быстрее |
|||
142
Z1
02.09.10
✎
19:09
|
PS к 140
сбособ 1 надо применять практически в 99% написанных ВАМИ прямых запросов 1сpp. т.е. когда Вы не применяете способ1 Вы должны понимать почему Вы этого не делаете. |
|||
143
Dmitriy Kolyasnikov
02.09.10
✎
19:59
|
(141) спасибо огромное за разъяснения!
>план выполнения отработанного запроса УДАЛЯЕТСЯ из буфера выполнения не сразу получается, даже без разницы из одного сеанса был запущен запрос или из разных, план выполнения доступен всегда, пока он находится в кэше? |
|||
144
Ковычки
02.09.10
✎
20:43
|
Проверьте в MS SQL 2000 конструкцию
select top (asc(-10)) * from _1sjourn order by (-iddocdef) |
|||
145
Ковычки
02.09.10
✎
20:49
|
и попутно, где можно взять MSSQL 7.0 намекните
|
|||
146
Dmitriy Kolyasnikov
03.09.10
✎
11:01
|
(137)
>глЗапрос.УстановитьТекстовыйПараметр("ИДРеализации",ВыбДок); поставил здесь ВыбДок.ТекущийДокумент() :) вылезло в таком цикле: докЗаявка = СоздатьОбъект("Документ.ЗаявкаПокупателя"); докЗаявка.ВыбратьДокументы(Дата(2010,07,01), ТекущаяДата()); Пока докЗаявка.ПолучитьДокумент() = 1 Цикл Сообщить(""+докЗаявка+" - "+глФлагРНК(докЗаявка)); КонецЦикла; |
|||
147
Dmitriy Kolyasnikov
03.09.10
✎
11:04
|
+(146) в том запросе, о котором говорили в (137) - там всегда ссылка передается, а в другие функции передаются и сами документы.
|
|||
148
smaharbA
03.09.10
✎
11:15
|
Тут подумалось на медне, а с чего это при выборке подчиненных должно "рвать крышу" у скуля - передается строка, ну и фиг на нее
|
|||
149
Dmitriy Kolyasnikov
07.09.10
✎
14:38
|
вощем копаю в сторону переписать общий журнал от руки в виде обработки.
подскажите можно ли как-то изящно в одном запросе сразу же выбрать поля СуммаВзаиморасчетов и Контрагент из шапок документов? или все же лучше сначала делать запрос к журналу, а потом дергать построчно из таблиц документов? Пока только такой вариант в голову приходит (т.е. это отбор из ВСЕХ таблиц документов): СкульЗапрос = " |SELECT | Journ.IDDOC as [Док $Документ], | Journ.IDDOCDEF as Док_вид, | CAST(LEFT(Journ.Date_Time_IDDoc, 8) as DateTime) as ДатаДок, | Journ.DOCNO as НомерДок, | Journ.CLOSED as Проведен, | Journ.ISMARK as Помечен, | COALESCE ($ДокР.Контрагент, $ДокЗ.Контрагент, ...) as [Контрагент $Справочник.Контрагенты] | COALESCE ($ДокР.СуммаВзаиморасчетов, $ДокЗ.СуммаВзаиморасчетов, ...) as СуммаВзаиморасчетов |FROM | _1SJOURN AS JOURN (NOLOCK) |LEFT JOIN | $Документ.Реализация as ДокР (NOLOCK) ON (ДокР.IDDOC = JOURN.IDDOC) |LEFT JOIN | $Документ.ЗаявкаПокупателя as ДокЗ (NOLOCK) ON (ДокЗ.IDDOC = JOURN.IDDOC) |LEFT JOIN |... и так все документы |"; |
|||
150
Dmitriy Kolyasnikov
07.09.10
✎
14:41
|
+(149) если отбирать сначала по журналу, а потом построчно дергать данные из документов стандартными процедурами как и в общем журнале, то при условии, что выбран отбор по Контрагенту - на периодах до года считает таблицу в пределах 3 секунд.
|
|||
151
Dmitriy Kolyasnikov
07.09.10
✎
14:44
|
+(150) отбор по контрагенту делаю так:
СкульЗапрос=СкульЗапрос+" |INNER JOIN | _1SCRDOC AS OTBOR (NOLOCK) ON (OTBOR.ChildID = JOURN.IDDoc AND | OTBOR.MDID = $ГрафаОтбора.Контрагент AND | OTBOR.ParentVal = :ВыбКонтрагент* AND | OTBOR.Child_Date_Time_IDDoc BETWEEN :НачДата AND :КонДата~) |ORDER BY | OTBOR.CHILD_DATE_TIME_IDDOC"; |
|||
152
МихаилМ
07.09.10
✎
15:05
|
в плане запроса сколько занимает ORDER BY в случае несовпадения, как у Вас
индекса отбора и упорядочивания. такие упорядочивания делаютя на клиенте. |
|||
153
МихаилМ
07.09.10
✎
15:18
|
в (149) в запросе ошибка:
тк в COALESCE могут попать данные из разных документов. лучше сначала выбрать из _1SJOURN во временную таблицу с индексов по IDDOCDEF а потом SELECT... UNION - LEFT JOIN неудачное решение. и не забыть, что драйвер одбс возвращает первый селект те не забыть сет рок коунт оф-он |
|||
154
Dmitriy Kolyasnikov
07.09.10
✎
15:39
|
+(152) посмотрел в профайлере, планы с ордербай и без него - одинаковые... разницы по duration тоже не заметил...
вот если сделать по JOURN.DATE_TIME_IDDOC, то тогда показывает в плане на сортировку 2%: |INNER JOIN | _1SCRDOC AS OTBOR (NOLOCK) ON (OTBOR.ChildID = JOURN.IDDoc AND | OTBOR.MDID = $ГрафаОтбора.Контрагент AND | OTBOR.ParentVal = :ВыбКонтрагент* AND | OTBOR.Child_Date_Time_IDDoc BETWEEN :НачДата AND :КонДата~) |ORDER BY | JOURN.DATE_TIME_IDDOC"; |
|||
155
Dmitriy Kolyasnikov
07.09.10
✎
17:08
|
(153) Идея с временной таблицей подмогла! UNION не осилил, сделал через курсор :) В 1С пока не переносил, но в скуле вижу, что работает! суммы проверил - выбирает верно.
В качестве курсора взял тот же свой запрос за год по клиенту. Ниже 2 селекта с назначением i3 - это выборки полей "СуммаВзаиморасчетов" по таблицам документов "Реализация" и "ЗаявкаПокупателя", так же можно все виды документов перебрать, сразу получая и сумму документа, и контрагента. drop table #temp_journ create table #temp_journ( IDDOC [char](9) NOT NULL, IDDOCDEF [int] NOT NULL, DOCSUM [numeric](14, 2)) declare @i1 char(9), @i2 int, i3 numeric(14,2) declare Journ_cursor CURSOR LOCAL FOR SELECT Journ.IDDOC, Journ.IDDOCDEF FROM _1SJOURN AS JOURN (NOLOCK) INNER JOIN _1SCRDOC AS OTBOR (NOLOCK) ON (OTBOR.ChildID = JOURN.IDDoc AND OTBOR.MDID = 862 AND OTBOR.ParentVal = 'B1 4S X5 ' AND OTBOR.Child_Date_Time_IDDoc BETWEEN '20100101' AND '20100907Z') OPEN Journ_cursor FETCH NEXT FROM Journ_cursor INTO @i1, @i2 WHILE @@FETCH_STATUS = 0 BEGIN set i3 = 0 if @i2 = 2457 begin set i3 = (select top 1 SP2443 from DH2457 with (nolock) where IDDOC = @i1) end if @i2 = 1611 begin set i3 = (select top 1 SP1594 from DH1611 with (nolock) where IDDOC = @i1) end insert into #temp_journ (IDDOC, IDDOCDEF, DOCSUM) VALUES (@i1, @i2, i3) FETCH NEXT FROM Journ_cursor INTO @i1, @i2 END CLOSE Journ_cursor DEALLOCATE Journ_cursor select * from #temp_journ |
|||
156
smaharbA
07.09.10
✎
17:10
|
Нашел по случаю одну байду
в терминале если не запрещено в конфигурации контактной зоны, то админ подключается из адинес по именованному каналу, в то время как простые усеры по тсп/ип |
|||
157
Dmitriy Kolyasnikov
07.09.10
✎
17:11
|
+(155) форум все переконвертил по-своему :( везде где написано registered-user бла-бла-бла - это переменная i3
"@i3" не знаю как её написать чтобы форум не переделывал :( |
|||
158
Dmitriy Kolyasnikov
08.09.10
✎
07:44
|
+(155) побил запрос с курсором на 2 части, в первой заполняю временную таблицу, во второй части делаю из нее селект без отбора. При выполнении в Management studio все отлично работает, а при выполнении из 1С во временную таблицу пишутся только первые 69-74 строки не зависимо от выбранного периода :(
|
|||
159
orefkov
08.09.10
✎
08:21
|
(149)
Курсоры и врем-таблицы не надо. Твой 1ый вариант хорош, только его надо чуть оптимизнуть: |SELECT | Journ.IDDOC as [Док $Документ], | Journ.IDDOCDEF as Док_вид, | CAST(LEFT(Journ.Date_Time_IDDoc, 8) as DateTime) as ДатаДок, | Journ.DOCNO as НомерДок, | Journ.CLOSED as Проведен, | Journ.ISMARK as Помечен, | COALESCE ($ДокР.Контрагент, $ДокЗ.Контрагент, ...) as [Контрагент $Справочник.Контрагенты] | COALESCE ($ДокР.СуммаВзаиморасчетов, $ДокЗ.СуммаВзаиморасчетов, ...) as СуммаВзаиморасчетов |FROM | _1SJOURN AS JOURN (NOLOCK) |LEFT JOIN | $Документ.Реализация as ДокР (NOLOCK) ON (ДокР.IDDOC = JOURN.IDDOC and JOURN.iddocef = $ВидДокумента.Реализация) |LEFT JOIN | $Документ.ЗаявкаПокупателя as ДокЗ (NOLOCK) ON (ДокЗ.IDDOC = JOURN.IDDOC and JOURN.iddocef = $ВидДокумента.ЗаявкаПокупателя) |LEFT JOIN те сделать так, чтобы сервер не лазил в ненужные таблицы |
|||
160
Dmitriy Kolyasnikov
08.09.10
✎
08:39
|
(159) гыы :) да уж, так попроще будет :)
всё же хочется понять почему ТОТ ЖЕ САМЫЙ курсор при вызове из 1С отрабатывает только около 70 строк :( тот же самый - т.е. я его прямо по Ctrl-C Ctrl-V перетаскиваю из Management Studio в 1С. Курсор хорош тем, что прямо там в том же запросе я попутно могу собирать информацию об оплате, помечать профинансированные факторинговыми компаниями документы и т.д. и т.п. Время выполнения запроса с курсором это позволяет вполне. |
|||
161
orefkov
08.09.10
✎
08:50
|
(160)
Рискну предложить поставить в начале скрипта set nocount on Часто это помогает. (157) о, дыра в движке мисты? |
|||
162
Dmitriy Kolyasnikov
08.09.10
✎
09:01
|
(161) >set nocount on
да! так работает! спасибо! nocount включал только на время работы курсора. При этом в самом курсоре добавил top 500 - работает, типа если больше - извините, укажите более точный период. |
|||
163
Dmitriy Kolyasnikov
08.09.10
✎
11:59
|
запрос (159) отрабатывает мгновенно. Ну и раз нарисовался такой запрос, пытаюсь все же обойтись без курсора и временной таблицы и сделать параметризованный запрос.
Добавил еще один LEFT JOIN, в котором ищу подчиненную проведенную реализацию у заявок. Работает не пойми как долго, перебором построчно собрал бы эти данные за 1,5-2 секунды, а запрос работает секунд 25-30. Результат возвращает неправильный (ни одной реализации не находит). Не могу найти где ошибка :( СкульЗапрос = " |SELECT | Journ.IDDOC as [Док $Документ], | Journ.IDDOCDEF as Док_вид, | CAST(LEFT(Journ.Date_Time_IDDoc, 8) as DateTime) as ДатаДок, | Journ.DOCNO as НомерДок, | Journ.CLOSED as Проведен, | Journ.ISMARK as Помечен, | COALESCE ($ДокР.Контрагент, $ДокЗ.Контрагент) as [Контрагент $Справочник.Контрагенты], | COALESCE ($ДокР.СуммаВзаиморасчетов, $ДокЗ.СуммаВзаиморасчетов) as СуммаВзаиморасчетов, | COALESCE (flag.fl,99) as ФлагРНК |FROM | _1SJOURN AS JOURN (NOLOCK) |LEFT JOIN $Документ.ЗаявкаПокупателя as ДокЗ (NOLOCK) ON (ДокЗ.IDDOC = JOURN.IDDOC | and JOURN.iddocdef = $ВидДокумента.ЗаявкаПокупателя) |LEFT JOIN $Документ.Реализация as ДокР (NOLOCK) ON (ДокР.IDDOC = JOURN.IDDOC | and JOURN.iddocdef = $ВидДокумента.Реализация) |--__________________ здесь отбор подчиненной реализации ____________ |LEFT JOIN | (SELECT top 1 | 1 as fl, | TabRod.CHILDID as IDDOC | FROM | _1SCRDOC As TabRod(NOLOCK) | INNER JOIN | _1SJOURN As TabJ(NOLOCK) ON (TabRod.CHILDID = TabJ.IDDOC) | WHERE | TabRod.MDID = 0 | And TabRod.PARENTVAL = ('O1'+$ВидДокумента36.ЗаявкаПокупателя+TabJ.IDDOC) | And TabJ.IDDOCDEF = $ВидДокумента.Реализация | And TabJ.CLOSED > 0) flag ON (flag.IDDOC = JOURN.IDDOC and JOURN.iddocdef = $ВидДокумента.ЗаявкаПокупателя) |-- _______________________ закончен отбор _________________________ |INNER JOIN | _1SCRDOC AS OTBOR (NOLOCK) ON (OTBOR.ChildID = JOURN.IDDoc AND | OTBOR.MDID = $ГрафаОтбора.Контрагент AND | OTBOR.ParentVal = :ВыбКонтрагент* AND | OTBOR.Child_Date_Time_IDDoc BETWEEN :НачДата AND :КонДата~) |ORDER BY | OTBOR.CHILD_DATE_TIME_IDDOC"; |
|||
164
МихаилМ
08.09.10
✎
12:24
|
(163)
может скл > 2000 умнее отрабатывает джоин (селект ...) а 2000 очень неудачно ошибка естественно в джоин (селект топ 1) Вы делаете запросы как-то странно. применяйте принцып декомпозиции-композиции (разделяй и властвуй) те временные таблицы. после отладки можете собрать в 1 запрос. естественно что запрос в ssms и в 1c77 будет отрабатывать по разному ssms работает через oledb а 1с через odbc oledb оледиби возвращает последний рез запроса а одибиси - первый это указано в документации по 1с++ уже писал Вам, что >1 COALESCE - источник трудноНаходимых ошибок. и про сортировку писал. |
|||
165
Dmitriy Kolyasnikov
08.09.10
✎
14:25
|
(164)
>уже писал Вам, что >1 COALESCE >- источник трудноНаходимых ошибок. >и про сортировку писал. Михаил! Я не из вредности, мне просто иногда бывает трудно получить практическую информацию из ваших очень лаконичных ответов, т.к. моё кунг-фу намного слабее :) например этот совет: "и не забыть, что драйвер одбс возвращает первый селект те не забыть сет рок коунт оф-он" без помощи гугла мне это не понять, и что здесь гуглить - тоже не совсем понятно. Подозреваю, это на ту же тему, что и (161). про сортировку - Вы меня отослали к плану запроса, и я проверил, что план не меняется от наличия или отсутствия ORDER BY. Я убедился, что если подставить сортировку по полю из _1SJOURN вместо _1SCRDOC, то сортировка появляется в плане запроса. Я полагал, что в моем случае все же сортировка не мешает работе, т.к. на нее не выделено время в плане запроса. Это неверно? > тк в COALESCE могут попать данные из разных документов. >уже писал Вам, что >1 COALESCE - источник трудноНаходимых ошибок. тоже хочу уточнить. В каждый COALESCE у меня попадают данные сугубо одного типа. В каждом COALESCE по каждой строке запроса после совета (159) на мой взгляд заведомо содержится только одно ненулевое значение. Ведь даже если предположить, что в таблице каждого документа найдется документ с подходящим IDDOC, с фильтром по IDDOCDEF реально в запросе по каждой строке присоединится только одна таблица документа. В чем моя логика ошибочна? За счет чего я могу словить данные из разных документов в COALESCE? |
|||
166
МихаилМ
08.09.10
✎
14:48
|
(165)
сет рок коунт оф-он читать, как в (161) set nocount on --------------------- я не не готов Вам разжовывать, в надежде, что Вы специалист и умеете работать с документацией. вижу своей задачей только ПОДСКАЗАТЬ, если что-то забыли или пропустили. |
|||
167
Z1
08.09.10
✎
15:30
|
(163) попробуйте вместо COALESCE использовать CASE.
по самому запросу трудно что либо сказать потому что не понятно какую точно Вы решаете задачу. |
|||
168
Z1
08.09.10
✎
15:40
|
>>>про сортировку - Вы меня отослали к плану запроса, и я проверил, что план не >>>меняется от наличия или отсутствия ORDER BY. Я убедился, что если подставить >>>сортировку по полю из _1SJOURN вместо _1SCRDOC, то сортировка появляется в >>>плане запроса. Я полагал, что в моем случае все же сортировка не мешает >>>работе, т.к. на нее не выделено время в плане запроса. Это неверно?
Вы неправильно предполагаете что для одного и того же запроса ПланВыполнения неизменен во времени. Для одного и того же исходного запроса sql сервер может строить разные планы.так что все дальнейшие Ваши рассуждения про сортировку не верны если нет ORDER BY то данные могут быть выведены с использованием индекса ( и при этом совпадут с порядком индекса и 95% случаев так и происходит ) но sql сервер этого делать не обязан и может вывести даже неупорядоченный набор. когда есть ORDER BY то sql выходной набор обязательно будет упорядочен ( ну формально даже не важно как это sql сделает найдет ли подходящий индекс или сам как-то выполнит сортировку ) |
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |