Имя: Пароль:
1C
1C 7.7
v7: Проблема с табличным полем. 1С++
,
0 Mutniy2
 
04.03.15
18:35
Есть череда документов для склада, как-то Розничная, Расходная, Перемещение, Счет и т.п.
Эти виды документов ставятся на сборку и склад их собирает.
Документ ставится на сборку изменением статуса и даты "Собрать к".
Соответственно есть журнал сборки на основе табличного поля, запрос типичный
    |      _1SJourn as Жур (NOLOCK)
    |     LEFT JOIN $Документ.РасходнаяНакладная as ДокРН (NOLOCK) ON (ДокРН.IDDoc = Жур.IDDoc)
    |     LEFT JOIN $Документ.РасходнаяРозничная as ДокРР (NOLOCK) ON (ДокРР.IDDoc = Жур.IDDoc AND $ДокРР.ЧекНаВозврат = 0)
    |     LEFT JOIN $Документ.Счет as ДокСЧ (NOLOCK) ON (ДокСЧ.IDDoc = Жур.IDDoc)
    |     LEFT JOIN $Документ.ЗаявкаНаОтгрузкуЗаНал as ДокЗНал (NOLOCK) ON (ДокЗНал.IDDoc = Жур.IDDoc)
    |     LEFT JOIN $Документ.Перемещение as ДокПерем (NOLOCK) ON (ДокПерем.IDDoc = Жур.IDDoc)

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

Как теоретически ускорить запрос?
Кто-нить со вьювами работал? сделал вьюв по выборке, подумал его индексировать, но уперся в "Cannot create index on view 'JournAssembly2015' because the view is not schema bound".
У кого есть опыт работы со вьювами в скуле?
1 Mutniy2
 
04.03.15
18:35
какие условия надо соблюсти, что-бы его можно было проиндексировать?
2 Mutniy2
 
04.03.15
18:36
Уже всю голову сломал.
3 Zhuravlik
 
04.03.15
18:40
За скуль не знаю. Но помню, когда возился с подобным для ДБФ (SQLiteDataProvider) - запрос выполнялся для видимых строк. Не помню вот это свойство ТП или SQlite. А то может имеет смысл еще раз перечитать доку :)
4 Mutniy2
 
04.03.15
18:43
(3) Да вот курю доки. Уже пол дня.
Фиговый табачек у мелкософта - у меня 2 скуля, 2000 и 2005 в работе, на 2005 дока на мелкосайте есть, а по 2000-му только BOL на скврноинглише.
5 Zhuravlik
 
04.03.15
18:50
Поднял CHM от SQLite, формировать запрос лишь для видимых - это прерогатива SQLiteDataProvider, ТП так не умеет само по себе. У ТП вроде как поставщик необходимо объявлять? ИМХО надо сначала проработать этот вопрос с ним. Когда читал доку по 1С++ точно помню было сколько-то инфы о разл. поставщиках.
6 Mutniy2
 
04.03.15
18:54
Тема по MS SQL-серверу. И оптимизаднице запросов.
7 Mutniy2
 
04.03.15
18:54
На всякий.
8 Serginio1
 
04.03.15
18:55
Я обычно в условие добавляю ВидДокумента

LEFT JOIN $Документ.РасходнаяНакладная as ДокРН (NOLOCK) ON (Жур.IDDocDef=$ВидДокумента.РасходнаяНакладная)
And (ДокРН.IDDoc = Жур.IDDoc)
9 Mutniy2
 
04.03.15
19:03
Это есть.
10 Herby
 
04.03.15
19:18
>проблема в том, что если интервал дат большой, журнал
>будет тормозить при выборке. Соответственно

я что-то не понимаю почему он тормозит на большом периоде?

при связке Табличное Поле + Поставщик: "ODBCDataProvider.MSSQL"
выполняется select top <количество видимых строк>.

и в этом случае период вообще не должен влиять на тормоза...
11 Herby
 
04.03.15
19:20
у меня "достаточно тяжелые запросы", но при связке Табличное Поле + Поставщик: "ODBCDataProvider.MSSQL" у меня все выстреливает как из пушки.
12 Злопчинский
 
04.03.15
19:55
а не надо путать счета (сфера ответсвенности манагеров) и задания на сборку (сфера ответственности склада).
13 ADirks
 
05.03.15
10:27
(0) Например, создать свою табличку, писать туда нужную для отбора инфу. На эту табличку навесить правильный индекс. Инфу писать триггерами.
В общем, это типа как-бы "графа отбора", только грамотно сделанная.

Ещё, когда у тебя в запросе используются шапки док-ов разного вида, то лучше не лепить кучу джойнов, а делать так:
select
    Журн.Date_Time_IDDOC as Порядок,
    Журн.идДок13 as Документ,
    (6*Журн.IsMark + (Журн.Closed&1)) as Пиктограмма,
    Журн.НомерДок as Номер,
    Left(Журн.Date_Time_IDDOC, 8) as Дата,
    Док.ВидДок as ВидДок,
    Док.Касса as Касса,
    Док.Приход as Приход,
    Док.Расход as Расход
from
    ЖурналДокументов Журн
    LEFT JOIN (
        SELECT
            'ПКО' ВидДок,
            Док.идДок9,
            Док.Сумма Приход,
            0.00 Расход,
        FROM
            докПриходныйОрдер Док
        
        UNION ALL
            
        SELECT
            'РКО' ВидДок,
            Док.идДок9,
            Док.Касса,
            0.00 Приход,
            Док.Сумма Расход,
        FROM
            докРасходныйОрдер Док
        
        UNION ALL
        ...

    ) Док ON Док.идДок9 = Журн.идДок9
where
    Журн.IDDocDef IN (2306, 11087, 2296, 11097, 38560, 2574)
14 Ёпрст
 
05.03.15
10:33
(13) ЖурналДокументов, идДок13 .... ты сейчас взорвешь автору мозг :)
15 ADirks
 
05.03.15
10:40
(14) да ладно, смысл то понятен, я думаю
человек вьюхи упоминал, стало быть в курсе
16 Mutniy2
 
05.03.15
10:44
да, код понятен.
17 Serginio1
 
05.03.15
10:48
(13) Тогда уж

SELECT Реализация.IDDOC [Ссылка $Документ.Реализация]
FROM _1SJOURN AS Журнал With (NOLOCK)
    INNER JOIN $Документ.Реализация AS Реализация With (NOLOCK) ON Журнал.IDDOC = Реализация.IDDOC
WHERE (Журнал.IDDOCDEF = :ВидДок)

And (Cast(Left(Журнал.DATE_TIME_IDDOC, 8) AS datetime) >= :НачДата)
    AND (Cast(Left(Журнал.DATE_TIME_IDDOC, 8) AS datetime) <= :КонДата)

Union
.....

Так как по IDDOCDEF  есть индекс IDDOCDEF,DATE_TIME_IDDOC
18 Ёпрст
 
05.03.15
10:52
(17) смысла нет, ну, т.е в производительности не выиграешь
19 Serginio1
 
05.03.15
10:53
Есть конечно еще выделить их в журнал и отбирать по журналу

IDJOURNAL,DATE_TIME_IDDOC
Или использовать графу отбора
20 Mutniy2
 
05.03.15
10:55
А индексированную вьюху по шапкам шескольких документов приходилось кому делать? Срослось?
21 Serginio1
 
05.03.15
10:59
(18) Аргументируй.
По сравнению с первым ему придется пройтись по всему журналу в том числе по тем видам которых нет в списке. И если таких документов будет много то выигрыш будет явным.

В любом случае в (0) Соединение идет без учета вида документа (13).
  Пусть автор выдаст данные эксперимента
22 ADirks
 
05.03.15
11:24
(21) индекс по IDDocDef задействуется условием
where
    Журн.IDDocDef IN (2306, 11087, 2296, 11097, 38560, 2574)
а также сортировкой по Date_Time_IDDoc, которое потом ТП накладывает. Большего не выжмешь.

(20) Пытались в своё время в этом направлении копать, но что-то не вышло. Что именно не устроило даже не помню. Собственно, тогда и остановились на вспомогательных табличках.
23 Mutniy2
 
05.03.15
11:28
(22) > Пытались в своё время в этом направлении копать, но что-то не вышло.

Да вот тоже вчера не вышло. Индекс невозможно построить если вюха не в схеме, а если вьюха в схеме, то начинаются другие проблемы.
Хотел проблемы переложить на секвак, но не вышло.
24 Serginio1
 
05.03.15
11:28
(18) А как отобрать документы по дополнительному жкрналу?
Понятно что _1scrdoc MdId
а есть аналог как $ГрафаОтбора ?
25 Mutniy2
 
05.03.15
11:28
Хотя вьюха, даже не индексированная, дает определенный выигрыш по производительности на клиенте.
26 ADirks
 
05.03.15
11:30
(25) самое главное преимущество вьюх - это то, что запросы можно писать по русски, без всяких метапарсеров :)
27 Serginio1
 
05.03.15
11:34
(22) Еще раз внимательно прочитай (21).
Тебе придется пройтись по строкам всего журнала и отбрасывать по ходу ненужные и если таких позиций много ты будешь терять на этом время. Хотя конечно это копейки.
28 Serginio1
 
05.03.15
11:35
27+ у него проблема с большой выборкой. А вообще обычная болезнь искать глазами в журнале, а не алгоритмами поиска
29 Ёпрст
 
05.03.15
11:36
(27) неа, будет индекс сик в плане запроса и задействован индекс по виду дока
30 ADirks
 
05.03.15
11:56
(27) нафиг мне читать (21), когда я могу почитать план запроса? И он кажет индекс скан по IDDOCTYPE (0%) + seek по PK (49%)  + clustered index seek по табличкам документов (48% в сумме)
31 Serginio1
 
05.03.15
12:28
(29,30) Каюсь был неправ.
Ёпрст ответь на вопрос в 24
32 Ёпрст
 
05.03.15
12:48
(24) разве что свою табличку лепить
33 Mutniy2
 
05.03.15
12:53
(26) > самое главное преимущество вьюх - это то, что запросы можно писать по русски, без всяких метапарсеров :)

Ну так тоже самое может дать обычная табличка+тригеры.
34 ADirks
 
05.03.15
13:07
(33) да не, я про другое
у меня на все 1С-ные таблички (справочники, документы, журналы, регистры) автоматически генерируются вьюхи с русскими именами. После чего я могу писать запросы по русски, как в 1С, так и в SSMS. Очень удобно.
35 ADirks
 
05.03.15
13:09
т.е. это тупые синонимы табличек, к примеру:

CREATE VIEW [dbo].[докАвансовыйОтчет] AS
SELECT
    IDDoc,
    IDDoc идДок9,
    SP12956 Комментарий,
    SP50802 Изменение,
    SP3192 Сотрудник,
    SP3193 НаименованиеАванса,
    SP3194 ПредОстаток,
    SP3195 ТипОстатка,
    SP3196 ПриложеноДок,
    SP3197 Получено1,
    SP3198 Дата1,
    SP3199 Сумма1,
    SP3200 Получено2,
    SP3201 Дата2,
    SP3202 Сумма2,
    SP3203 Получено3,
    SP3204 Дата3,
    SP3205 Сумма3,
    SP7902 Валюта,
    SP20606 НаЛистах,
    SP23645 ВерсияОбъекта,
    SP52011 Фирма,
    SP3208 Сумма,
    SP20608 СуммаПоОтчету
FROM DH3191 WITH (NoLock)
36 Mutniy2
 
05.03.15
13:16
(34) Понятно. Не слишком ты загемороил попусту сервак?
На поддержание вьюва нужны ресурсы.
37 trad
 
05.03.15
13:23
(24) ты не поверишь, но
mdid = $ЖурналДокументов.ТвойДопЖурнал
38 Ёпрст
 
05.03.15
13:58
(37) я думаю, он немного про другое спрашивал, не ?..
39 trad
 
05.03.15
14:00
(38) я думаю он это и спрашивал
"А как отобрать документы по дополнительному жкрналу? "
документы по доп журналу отбираются из _1scrdoc c условием как я указал
40 Serginio1
 
05.03.15
14:15
(36) Спасибо так и предполагал, но не нашел в интернете использования $ЖурналДокументов

Упущение это исправлю для выборки по дополнительному журналу

SELECT Журнал.IDDOC [Документ $Документ]
    , Журнал.IDDOCDEF [Документ_вид $ВидДокументаПредставление]
    , Журнал.DOCNO Документ_ном
    , NullIf(Cast(Left(Журнал.DATE_TIME_IDDOC, 8) AS datetime), '17530101') ЖурналДокумент_дата
FROM _1SCRDOC AS Отбор With (NOLOCK)
    INNER JOIN _1SJOURN AS Журнал With (NOLOCK) ON Отбор.CHILDID = Журнал.IDDOC
WHERE (Отбор.MDID = $ЖурналДокументов.ИзмененияСостояния)
    AND (Cast(Left(Отбор.CHILD_DATE_TIME_IDDOC, 8) AS datetime) >= :НачДата)
    AND (Cast(Left(Отбор.CHILD_DATE_TIME_IDDOC, 8) AS datetime) <= :КонДата)
41 trad
 
05.03.15
15:13
(40) (Cast(Left(Отбор.CHILD_DATE_TIME_IDDOC, 8) AS datetime) >= :НачДата)

вот это все портит, ты не попадаешь в индекс и сканируешь весь журнал вне зависимости о дат

надо так
and Отбор.CHILD_DATE_TIME_IDDOC > :НачДата
and Отбор.CHILD_DATE_TIME_IDDOC < :КонДата~
или between
42 trad
 
05.03.15
15:18
(40) и еще
если вместо
ON Отбор.CHILDID = Журнал.IDDOC
написать так
ON Отбор.CHILD_DATE_TIME_IDDOC = Журнал.DATE_TIME_IDDOC
или так
ON right(Отбор.CHILD_DATE_TIME_IDDOC,9) = Журнал.IDDOC
то избавишься от ненужного bookmark lookup
43 Serginio1
 
05.03.15
15:59
(41) Я конструкторм пользуюсь. Лениво руками править. Но обычно использую between

А вот со 42 не совсем согласен, т.к. по IDDOC индекс и он короче а значит страниц с индексом меньше и поиск быстрее.
44 trad
 
05.03.15
16:11
(43) "Я конструкторм пользуюсь. Лениво руками править. Но обычно использую between "
дело то не в битвине

"А вот со 42 не совсем согласен..."
уговаривать не стану
45 Злопчинский
 
05.03.15
16:14
Какие все умные я с вас балдею
46 Ёпрст
 
05.03.15
16:15
(45) лучше б спрашивал побольше, а не балдел
:))
47 Злопчинский
 
05.03.15
17:45
(45)  да вот надобности блин постоянной нет
Эпизодически только
Вот как начну свою нетленку кропать то тут меня и попрет понесет
Готовьтесь короче
48 Злопчинский
 
05.03.15
17:45
Блин правда я обещаю с 2013 года
49 Serginio1
 
06.03.15
10:27
(44) Посыл то я понял использовать данные индекса для соединения. Спасибо.
Со второй частью (42) я полностью согласен.
ON right(Отбор.CHILD_DATE_TIME_IDDOC,9) = Журнал.IDDOC

Что бы добить тему с отбором по виду журнала

SELECT Журнал.IDDOCDEF [Документ_вид $ВидДокументаПредставление]
    , Журнал.DOCNO Документ_ном
    , NullIf(Cast(Left(Журнал.DATE_TIME_IDDOC, 8) AS datetime), '17530101') Документ_дата
FROM _1SJOURN AS Журнал With (NOLOCK)
WHERE (IDJOURNAL=$ЖурналДокументов.ДокументыПоПокупателям)
And  (Cast(Left(Журнал.DATE_TIME_IDDOC, 8) AS datetime) >= :НачДата)
    AND (Cast(Left(Журнал.DATE_TIME_IDDOC, 8) AS datetime) <= :НачДата)

Сейчас не могу получить план запроса, но он и при таком условии отрабатывает мгновенно и точно не сканирует весь журнал. Хотя согласен, что правилнеее использовать

And   (Журнал.DATE_TIME_IDDOC >= :НачДата)
    AND (Журнал.DATE_TIME_IDDOC <= :НачДата~)
50 trad
 
06.03.15
10:47
(49) "но он и при таком условии отрабатывает мгновенно и точно не сканирует весь журнал"
ну да, в плане ты увидишь index seek, но seek этот будет только по полю IDJOURNAL ключа, а не по полному ключу
и записи в рамках конкретного значение IDJOURNAL он будет сканировать от начала времен до конца
я тебе это гарантирую
51 trad
 
06.03.15
10:52
обрати внимание на выражение в SEEK: в не правильном и правильном варианте

Index Seek(OBJECT:([xxx].[dbo].[_1SJOURN].[JOURNAL] AS [Журнал]), SEEK:([Журнал].[IDJOURNAL]=5026),  WHERE:(Convert(substring(Convert([Журнал].[DATE_TIME_IDDOC]), 1, 8))<='Jan 31 2015 12:00AM' AND Convert(substring(Convert([Журнал].[DA

Index Seek(OBJECT:([xxx].[dbo].[_1SJOURN].[JOURNAL] AS [Журнал]), SEEK:([Журнал].[IDJOURNAL]=5026 AND [Журнал].[DATE_TIME_IDDOC] >= '20150101' AND [Журнал].[DATE_TIME_IDDOC] <= '20150131z') ORDERED FORWARD)
52 Serginio1
 
06.03.15
11:02
(51) Какой SQL?
53 trad
 
06.03.15
11:12
2000
но это не имеет значения
54 Serginio1
 
06.03.15
11:19
(53) Согласен. Видно держит всю таблицу в памяти
Такой тоже отрабатывает незаметно на глаз.

SELECT  Журнал.DATE_TIME_IDDOC ДатаВремяИдДок
,Substring(Журнал.DATE_TIME_IDDOC,Len(Журнал.DATE_TIME_IDDOC)-3,4) Длина
FROM _1SJOURN AS Журнал With (NOLOCK)
WHERE (Substring(Журнал.DATE_TIME_IDDOC,Len(Журнал.DATE_TIME_IDDOC)-3,2) = 'IX')
55 trad
 
06.03.15
11:21
(54) "незаметно на глаз."
ну, это не научный метод
56 Serginio1
 
06.03.15
11:36
(55) Согласен. Время для прохода нескольких миллионов записей может быть меньше чем отправка данных по сети.