Имя: Пароль:
1C
 
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
(22) походу оно
спасибо Z1 и автору
буду думать
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
думаю как оставить такую конструкцию (может кто наведет на мысли)

глВыбратьПодчиненныеДокументы(Док,,,КонкретныйДоукмент);
Пока Док.ПолучитьДокумент() = 1 Цикл
КонецЦикла;
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
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с++ и Классе)

//-------------------------------------------------------------------------
Функция глВыбратьПодчиненныеДокументы(Док,ДатаНач="",ДатаКон="",ДокОсн,Вид="",Проведен=-1) Экспорт
// Функция получает выборку подчиненных документов
// Док - ссылка на документ СоздатьДокумент("Документ")
// ДатаНач - дата, документ или позиция начала выборки документов.
//           Если данный параметр опущен, то выборка начинается с самого первого существующего в системе документа.
// ДатаКон - дата, документ или позиция конца выборки документов.
//           Если данный параметр опущен, то выборка заканчивается самым последним существующим в системе документом.
// ДокОсн - документ, подчиненные которому будут включаться в выборку.
// Вид - вид документа. Если данный параметр опущен, то выбираются все документы.
// Проведен=1 - выбирать только проведенные.
// Проведен=0 - выбирать только не проведенные.
// Проведен=-1 - выбирать все документы.
   Перем Порядок,Тмп;
   Порядок=-1;
   Если ПустоеЗначение(ДатаНач)=1 Тогда
       Порядок=Док.ОбратныйПорядок(0);
       Если Док.ВыбратьДокументы()=1 Тогда
           Если Док.ПолучитьДокумент()=1 Тогда
               ДатаНач=Док.ТекущийДокумент();
           КонецЕсли;
       КонецЕсли;
   КонецЕсли;
   Если ПустоеЗначение(ДатаКон)=1 Тогда
       Тмп=Док.ОбратныйПорядок(1);
       Если Порядок=-1 Тогда
           Порядок=Тмп;
       КонецЕсли;
       Если Док.ВыбратьДокументы()=1 Тогда
           Если Док.ПолучитьДокумент()=1 Тогда
               ДатаКон=Док.ТекущийДокумент();
           КонецЕсли;
       КонецЕсли;
   КонецЕсли;
   Если Порядок>-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с++ - сравнивал с адо, прироста производительности не заметил)

//-----------------------------------------------
Функция глДокументСписокПодчиненныхSQL(Док,Реж=0,Знач Вид="",Знач ДатаНач='',Знач ДатаКон='',Соединение="",Знач Количество=2147483647,Подготов=0) Экспорт
// Формирует список документов подчиненных данному, возвращает размер списка. ДРК05
// Реж = 0-Все документы, 1-не помеченные, 2-проведенные, 3-не проведенные, 4-помеченные
// Вид-вид выбираемых документов и или список видов через запятую / все если пусто.
   Перем Стр,Сп,Тмп,Сч;
   СписокПодчиненных=СоздатьОбъект("СписокЗначений");
   Если ПустоеЗначение(Док)=1 Тогда Возврат 0; КонецЕсли;
   Если ТипЗначенияСтр(Соединение)="Стр" Тогда
       Тмп=СоздатьОбъект("ADODB.Connection");
       Тмп.cursorlocation=3;
       Тмп.open(Соединение);
       Соединение=Тмп;
   КонецЕсли;
   Если ТипЗначенияСтр(Вид)="СписокЗначений" Тогда
       Сп=СоздатьОбъект("СписокЗначений");
       Для Сч=1 По Вид.РазмерСписка() Цикл
           Стр=Вид.ПолучитьЗначение(Сч);
           Если ПустоеЗначение(Стр)=0 Тогда
               ИД=глПолучитьВидИД("Документ."+Стр);
               Если ИД>0 Тогда
                   Сп.ДобавитьЗначение(ИД);
               КонецЕсли;
           КонецЕсли;
       КонецЦикла;
       Виды=Сп.ВСтрокуСРазделителями();
   ИначеЕсли ТипЗначенияСтр(Вид)="Строка" Тогда
       Виды=СтрЗаменить(Вид," ","");
   Иначе
       Возврат 0;
   КонецЕсли;
   Тмп="";
   ВидИД=_IdToStr(глПолучитьВидИД(Док.ТекущийДокумент()));
   ДокИД=_IdToStr(глПолучитьОбъектИД(Док.ТекущийДокумент()));
   ДатаНач=глПолучитьПозициюВнутр(ДатаНач);
   Если ТипЗначенияСтр(ДатаКон)="Дата" Тогда
       ДатаКон=ДатаКон+1;
   КонецЕсли;
   ДатаКон=глПолучитьПозициюВнутр(ДатаКон);
   Помеченные=2;
   Проведенные=2;
   Если Реж=1 Тогда                // Не помеченные
       Помеченные=1;
   ИначеЕсли Реж=2 Тогда                // Проведенные
       Проведенные=0;
   ИначеЕсли Реж=3 Тогда                // Не Проведенные
       Проведенные=1;
   ИначеЕсли Реж=4 Тогда                // Помеченные
       Помеченные=0;
   КонецЕсли;
   Стр="
   |SELECT
   |TOP (ABS(?))
   |RTRIM(JOURN.IDDOC) AS IDDOC,JOURN.IDDOCDEF AS IDDOCDEF
   |from
   |    _1SJOURN JOURN(NOLOCK INDEX=ACDATETIME),
   |    _1SCRDOC CRDOC(NOLOCK INDEX=PARENT)
   |where
   |    JOURN.DATE_TIME_IDDOC=CRDOC.CHILD_DATE_TIME_IDDOC
   |and CRDOC.MDID=0
   |and CRDOC.PARENTVAL='O1'+RIGHT(?,4)+?
   |and CRDOC.CHILD_DATE_TIME_IDDOC>=?
   |and CRDOC.CHILD_DATE_TIME_IDDOC<?
   |and CHARINDEX(','+CAST(JOURN.IDDOCDEF AS VARCHAR)+',',','+?+',')>0
   |and JOURN.ISMARK<>?
   |and JOURN.CLOSED<>?
   |ORDER BY
   |CRDOC.MDID, CRDOC.PARENTVAL, CRDOC.CHILD_DATE_TIME_IDDOC ASC
   |";
   Если Подготов=1 Тогда
       Запрос1С.Подготовить(Стр);
       Запрос1С.ДобПараметр(1,4,8,0);
       Запрос1С.ДобПараметр(1,14,6,0);
       Запрос1С.ДобПараметр(1,14,6,0);
       Запрос1С.ДобПараметр(1,14,23,0);
       Запрос1С.ДобПараметр(1,14,23,0);
       Запрос1С.ДобПараметр(1,15,10,0);
       Запрос1С.ДобПараметр(1,4,8,0);
       Запрос1С.ДобПараметр(1,4,8,0);
       Подготовить=0;
   КонецЕсли;
   Сч=0;
   Запрос1С.УстПараметр(1,Количество);
   Запрос1С.УстПараметр(2,ВидИД);
   Запрос1С.УстПараметр(3,ДокИД);
   Запрос1С.УстПараметр(4,ДатаНач);
   Запрос1С.УстПараметр(5,ДатаКон);
   Запрос1С.УстПараметр(6,Виды);
   Запрос1С.УстПараметр(7,Помеченные);
   Запрос1С.УстПараметр(8,Проведенные);
   ТЗ=Запрос1С.ВыполнитьИнструкцию();
   ТЗ.ВыбратьСтроки();
   Пока ТЗ.ПолучитьСтроку()=1 Цикл
       Стр="{""O"",""0"",""0"","""+ТЗ.IDDOCDEF+""",""0"",""0"","""+Формат(_StrToId(ТЗ.IDDOC),"Ч10")+"   ""}";
       Тмп=ЗначениеИзСтрокиВнутр(Стр);
       СписокПодчиненных.ДобавитьЗначение(Тмп,глПечДок(Тмп));
       Сч=Сч+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 сделает найдет ли подходящий индекс
или сам как-то выполнит сортировку )