![]() |
![]() |
![]() |
|
v7: 1sqlite vs vfpoledb по сети | ☑ | ||
---|---|---|---|---|
0
Дык ё
08.12.12
✎
14:02
|
господа! помогите начинающему dbfнику
есть одинаковые по структуре запросы на vfpoledb и 1sqlite время выполнения локально: 350мс vfp, 17мс sqlite. тут все хорошо время выполнения по сети: ~7сек vfp, ~86сек sqlite. опаньки что я не учел? мне нужно по сети, и хочется 1sqlite http://dev.mista.ru/topic.php?id=554041 читал. судя по времени выполнения vfpoleb, дело не в кэшировании нужна помощь зала |
|||
1
kiruha
08.12.12
✎
14:13
|
Индексы в vfpoledb надо указывать вручную,
тогда время улучшится на порядок http://www.1cpp.ru/forum/YaBB.pl?num=1184317705 в 1sqlite они подбираются автоматически |
|||
2
Torquader
08.12.12
✎
14:13
|
Начнём с того, что SLQ-lite работает с dbf-файлами, то есть открывает просто файлы. При работе по сети, если работает только один клиент, система включает кеширование, так как уверена, что данные в самом файле не будут отличаться от кеша. Если работает несколько клиентов, то включается механизм очистки кеша - он не умеет отслеживать блоки в файлах, а только файлы целиком, то есть если один сеанс что-то записал в файл, то другой запрашивает этот файл снова с сервера (UDP-датаграммы туда и обратно) и получается, что за каждой строкой (а dbf-файлы обрабатываются построчно) система лазит на сервер.
И есть подозрение, что решения у данной проблемы нет, так как мы не можем лезть внутрь dll. |
|||
3
Torquader
08.12.12
✎
14:15
|
Кстати, vfp-драйвер работает с другим типом индексов - то есть напрямую заглянуть в 1С на запись не получится, а в случае чтения будет прямой выбор.
vfp- хорошо работает, если ему давать свои файлы - тогда работает и блокировка на время исполнения и пакеты запросов, но к 1С это относится также, как сторонний sql-сервер через OleDb. |
|||
4
kiruha
08.12.12
✎
14:20
|
(3)
dbf файл он и в Африке dbf Как и CDX P.S> тут полно людей которые работали на практике и на живых базах через сабж (0) |
|||
5
Aleksey
08.12.12
✎
14:21
|
(4) Не скажи, как раз в CDX и проблема ограничивающая прямую запись в dbf файл
|
|||
6
Дык ё
08.12.12
✎
14:36
|
(1) мне пока не надо лучше на порядок. достаточно будет быстрее, чем vfpoledb
(2) а почему vfpoledb страдает от этого на порядок меньше? основной вопрос в этом |
|||
7
Torquader
08.12.12
✎
14:40
|
(6) Если он индексы не читает, то он просто запрашивает один dbf-файл кусками, а в случае работы с индексами будет несколько запросов cdx-файлов, причём со смещением.
Есть подозрение, что при простом чтении dbf-файла читается не строка, а сразу блок строк (нужно смотреть как FoxPro устроен). |
|||
8
Холст
08.12.12
✎
14:41
|
||||
9
Torquader
08.12.12
✎
14:47
|
(8) В этом случае, файлы не открываются по сети, но за каждым файлом всё равно идёт обращение на сервер - единственное, что ускоряет процесс - отсутствие ожидания снятия блокировок со стороны других клиентов, так как можно просто подождать, пока файл освободиться, а не делать попытки его заблокировать, как делает это 1С.
|
|||
10
orefkov
08.12.12
✎
17:44
|
Запрос надо смотреть.
|
|||
11
Дык ё
08.12.12
✎
18:28
|
(10) в понедельник, запрос на работе остался. но локально то он в 20 раз быстрее :о
|
|||
12
Дык ё
10.12.12
✎
10:09
|
(10) в попытках переезда проверялось несколько запросов, и во всех случаях наблюдалась проблема из (0). запрос, о котором шла речь в (0) после отладки:
SELECT ltrim(nom.CODE) As Артикул , rtrim(nom.DESCR) As Наименование , fOST.НачОст , fOST.Приход , fOST.Расход , fOST.КонОст , fOST.Details AS Детализация , (2 - CASE WHEN fOST.НачОст = 0 THEN 1 ELSE 0 END - CASE WHEN fOST.Details = '' THEN 1 ELSE 0 END) AS флБылиДвижения FROM( SELECT Товар , Doc As Details, DateTime , Sum(НачОст) As НачОст , Sum(Приход) As Приход , Sum(Расход) As Расход , Sum(КонОст) As КонОст FROM ( SELECT itog.Товар As Товар , ' ' As Doc, ' ' As DateTime , itog.Количество As НачОст , 0 As Приход , 0 As Расход , itog.Количество As КонОст FROM РегистрИтоги_ОстаткиТоваров AS itog WHERE itog.PERIOD = '20121101' UNION ALL SELECT dv.Товар As Товар , CASE WHEN jrn.date >= '20121207' THEN jrn.iddocdef || jrn.iddoc ELSE ' ' END AS Doc , CASE WHEN jrn.date >= '20121207' THEN jrn.Date || jrn.Time ELSE ' ' END As DateTime , CASE WHEN jrn.date < '20121207' THEN (1-2*dv.debkred)*dv.Количество ELSE 0 END As НачОст , CASE WHEN (jrn.date >= '20121207') AND (dv.debkred = 0) THEN dv.Количество ELSE 0 END As Приход , CASE WHEN (jrn.date >= '20121207') AND (dv.debkred = 1) THEN dv.Количество ELSE 0 END As Расход , (1-2*dv.debkred)*dv.Количество As КонОст FROM Журнал As jrn INNER JOIN Регистр_ОстаткиТоваров As dv ON jrn.iddoc = dv.iddoc WHERE jrn.idx_DATE_TIME_IDDOC BETWEEN '20121201' AND '20121207Я' ) As OST GROUP BY Товар, Doc, DateTime ) As fOST LEFT JOIN Справочник_Номенклатура As nom ON nom.ID = fOST.Товар LEFT JOIN Справочник_Номенклатура As par1 ON par1.ID = nom.PARENTID LEFT JOIN Справочник_Номенклатура As par2 ON par2.ID = par1.PARENTID LEFT JOIN Справочник_Номенклатура As par3 ON par3.ID = par2.PARENTID LEFT JOIN Справочник_Номенклатура As par4 ON par4.ID = par3.PARENTID LEFT JOIN Справочник_Номенклатура As par5 ON par5.ID = par4.PARENTID LEFT JOIN Справочник_Номенклатура As par6 ON par6.ID = par5.PARENTID LEFT JOIN Справочник_Номенклатура As par7 ON par7.ID = par6.PARENTID LEFT JOIN Справочник_Номенклатура As par8 ON par8.ID = par7.PARENTID ORDER BY coalesce(par6.DESCR, par5.DESCR, par4.DESCR, par3.DESCR, par2.DESCR, par1.DESCR, '') , coalesce(par5.DESCR, par4.DESCR, par3.DESCR, par2.DESCR, par1.DESCR, '') , coalesce(par4.DESCR, par3.DESCR, par2.DESCR, par1.DESCR, '') , coalesce(par3.DESCR, par2.DESCR, par1.DESCR, '') , coalesce(par2.DESCR, par1.DESCR, '') , coalesce(par1.DESCR, '') , nom.DESCR, DateTime |
|||
13
Ёпрст
гуру
10.12.12
✎
10:15
|
(12) блин.. и не лень тебе было вот так писать:
from Регистр_ОстаткиТоваров JOIN Справочник_Номенклатура еще и перед запросом сами таблички эти задавал поди, да ? |
|||
14
Ёпрст
гуру
10.12.12
✎
10:17
|
да и проще флаг в регистр воткнуть, чем такое извращение с журналом в тексте запроса..
ну и ' ' в качестве "пустого" документа..оригинально. |
|||
15
Ёпрст
гуру
10.12.12
✎
10:24
|
и потом..
вот тут ты с '' сравниваешь when fOST.Details = '' а унутри пихаешь ' ' |
|||
16
Дык ё
10.12.12
✎
10:39
|
(13) зачем создавать? 1sqlite автоматом родные таблицы подключает ;-)
(14) я же говорю, переписываю запрос на vfpoledb (который писали до меня). задача на данном этапе - не красивый запрос, а сравнимая производительность |
|||
17
Ёпрст
гуру
10.12.12
✎
12:42
|
(16) а чего с производительностью ?
фокс при попадании в индекс всегда быстрее будет на таком запросе. |
|||
18
Ёпрст
гуру
10.12.12
✎
12:43
|
и не важно где - в сетки или локально
|
|||
19
Дык ё
10.12.12
✎
13:04
|
(17) мать-перемать! читай (0). локально sqlite быстрее в 20 раз, по сети на тех же запросах медленнее в 10 раз. вопрос - почему?
|
|||
20
kiruha
10.12.12
✎
13:14
|
(19)
Потому, что нет отборов тащишь по сетке Х Мб например здесь FROM РегистрИтоги_ОстаткиТоваров AS itog WHERE itog.PERIOD = '20121101' не понимаю зачем тогда нужны прямые - тупо выгружаешь регистр (ВыгрузитьИтоги) и дальше работаешь с ТЗ - скорость будет та же |
|||
21
Ёпрст
гуру
10.12.12
✎
13:15
|
(19) не задействован индекс в фоксе
|
|||
22
Дык ё
10.12.12
✎
13:22
|
(20) почему нет? 1sqlite в этом месте попадает в индекс PROP. и таки да, мне нужны остатки по всем товарам
(21) ты не поверишь... :-) |
|||
23
Ёпрст
гуру
10.12.12
✎
13:23
|
(22) ну дык покажи запрос на фоксе..
|
|||
24
Ёпрст
гуру
10.12.12
✎
13:24
|
а скульлайт по сети.. всегда тормоз, Орефков что-то объяснял по этому аоводу, не помню ужо.
|
|||
25
Ёпрст
гуру
10.12.12
✎
13:25
|
а фокс при попадании в индекс всегда будет быстрее на этом запросе (и локально в том числе)
|
|||
26
Дык ё
10.12.12
✎
13:25
|
(24) вспомни плиз, ты же все записываешь
|
|||
27
Дык ё
10.12.12
✎
13:32
|
(23) SELECT
iif(IsNull(par1.ID),1,iif(IsNull(par2.ID),2,iif(IsNull(par3.ID),3,iif(IsNull(par4.ID),4,iif(IsNull(par5.ID),5,iif(IsNull(par6.ID),6,7)))))) As _level, iif(not IsNull(par6.DESCR),par6.DESCR,iif(not IsNull(par5.DESCR),par5.DESCR,iif(not IsNull(par4.DESCR),par4.DESCR,iif(not IsNull(par3.DESCR),par3.DESCR,iif(not IsNull(par2.DESCR),par2.DESCR,iif(not IsNull(par1.DESCR),par1.DESCR,cast('' as char(80)))))))) As _exp1, iif(not IsNull(par5.DESCR),par5.DESCR,iif(not IsNull(par4.DESCR),par4.DESCR,iif(not IsNull(par3.DESCR),par3.DESCR,iif(not IsNull(par2.DESCR),par2.DESCR,iif(not IsNull(par1.DESCR),par1.DESCR,cast('' as char(80))))))) As _exp2, iif(not IsNull(par4.DESCR),par4.DESCR,iif(not IsNull(par3.DESCR),par3.DESCR,iif(not IsNull(par2.DESCR),par2.DESCR,iif(not IsNull(par1.DESCR),par1.DESCR,cast('' as char(80)))))) As _exp3, iif(not IsNull(par3.DESCR),par3.DESCR,iif(not IsNull(par2.DESCR),par2.DESCR,iif(not IsNull(par1.DESCR),par1.DESCR,cast('' as char(80))))) As _exp4, iif(not IsNull(par2.DESCR),par2.DESCR,iif(not IsNull(par1.DESCR),par1.DESCR,cast('' as char(80)))) As _exp5, iif(not IsNull(par1.DESCR),par1.DESCR,cast('' as char(80))) As _exp6, ltrim(nom.CODE) As TvrCODE, rtrim(nom.DESCR) As TvrDESCR, fOST.* FROM( SELECT Товар, Doc As Details, DateTime, Cast(Sum(НачОст) as Char(19)) As НачОст, Cast(Sum(Приход) as Char(19)) As Приход, Cast(Sum(Расход) as Char(19)) As Расход, Cast(Sum(КонОст) as Char(19)) As КонОст FROM( SELECT itog.sp5600 As Товар, ' ' As Doc, ' ' As DateTime, itog.sp5602 As НачОст, 0 As Приход, 0 As Расход, itog.sp5602 As КонОст FROM rg5599 As itog WHERE DTOS(itog.PERIOD) + itog.sp5601 like DTOS(Date(2012,11,1)) + '_______________' UNION ALL SELECT dv.sp5600 As Товар, iif(jrn.date >= Date(2012,12,10), jrn.iddocdef + jrn.iddoc, ' '), iif(jrn.date >= Date(2012,12,10), Dtos(jrn.Date) + jrn.Time, ' ') As DateTime, Cast(iif(jrn.date < Date(2012,12,10), (1-2*dv.debkred)*dv.sp5602, 0) as int) As НачОст, Cast(iif((jrn.date >= Date(2012,12,10)) AND (dv.debkred = 0), dv.sp5602, 0) as int) As Приход, Cast(iif((jrn.date >= Date(2012,12,10)) AND (dv.debkred = 1), dv.sp5602, 0) as int) As Расход, Cast((1-2*dv.debkred)*dv.sp5602 as int) As КонОст FROM ra5599 As dv INNER JOIN 1SJOURN As jrn ON jrn.iddoc = dv.iddoc WHERE DTOS(jrn.date)+jrn.time+jrn.iddoc BETWEEN Dtos(Date(2012,12,1)) + ' ' AND Dtos(Date(2012,12,10)) + 'ZZZZZZZZZZZZZZZ' ) As OST GROUP BY Товар, Doc, DateTime) As fOST INNER JOIN sc51 As nom ON nom.ID = fOST.Товар LEFT JOIN sc51 As par1 ON par1.ID = nom.PARENTID LEFT JOIN sc51 As par2 ON par2.ID = par1.PARENTID LEFT JOIN sc51 As par3 ON par3.ID = par2.PARENTID LEFT JOIN sc51 As par4 ON par4.ID = par3.PARENTID LEFT JOIN sc51 As par5 ON par5.ID = par4.PARENTID LEFT JOIN sc51 As par6 ON par6.ID = par5.PARENTID LEFT JOIN sc51 As par7 ON par7.ID = par6.PARENTID LEFT JOIN sc51 As par8 ON par8.ID = par7.PARENTID ORDER BY _exp1, _exp2, _exp3, _exp4, _exp5, _exp6, TvrDESCR, DateTime |
|||
28
kiruha
10.12.12
✎
13:34
|
Года 3 назад скачал sqlite ( не 1sqlite ! можно свободно с http://www.sqlite.org ).
Открыл - смотрю на реализацию Left Join - условно говоря 20 ! строчек кода , простой перебор. Малость офигел, вопросы снял |
|||
29
Ёпрст
гуру
10.12.12
✎
13:47
|
(27) а чего галку быстрая обработка движений не ставишь у регистра, или хотя бы отбор движений у любого измерения, чтоб индекс был на табличке движений.. ?
|
|||
30
Дык ё
10.12.12
✎
13:52
|
(29) вот жеж :-) я понимаю, как это можно оптимизировать. я не понимаю, почему (19)?
|
|||
31
Ёпрст
гуру
10.12.12
✎
13:57
|
да не помню я..тем более, баз по сети нема, что б даже проверить
:) |
|||
32
Ёпрст
гуру
10.12.12
✎
13:58
|
Орефкова пытай, это же его детище.
|
|||
33
Ёпрст
гуру
10.12.12
✎
14:00
|
Кстати, если воткнешь индекс на табличку движений, фокс обгонит скульлайт.. раз в 5.
Вот с соединением с журнальчиком, тоже не смог добиться скорости на фоксе. |
|||
34
orefkov
10.12.12
✎
14:05
|
(28)
Не надо песен. 1sqlite пишу с 2008 года, т.е. 4 года назад начинал. Где ты там в sqlite нашел реализацию лефт джойна в 20 строчек простым перебором - непонятно, наверное, ты плохо смотрел. |
|||
35
Ёпрст
гуру
10.12.12
✎
14:09
|
(34) а на счет падения скорости при выполнении запроса скульлайта по сети ?
|
|||
36
orefkov
10.12.12
✎
14:25
|
(12)
Первое и главное - цеплять всю иерархию в запросе - очень тяжело. sqlite для каждого джойна таблицы товаров дергает движок 1С, не кэшируя результаты. Лучше выгрузить без иерархии, и накрутить ее в ИТЗ, там и отсортируется. Раз быстрой обработки движений нет, воткни еще условие Журнал.ОстаткиТоваровФр = 1 |
|||
37
orefkov
10.12.12
✎
14:27
|
(35)
А можно еще попробовать взвести запрос.ВыполнятьВТранзакции Но однако, остальные будут обламываться на запись в регистр и журнал. |
|||
38
Ёпрст
гуру
10.12.12
✎
14:28
|
(37) не.. я не об этом.
Почему такое падение производительности ? |
|||
39
Ёпрст
гуру
10.12.12
✎
14:28
|
локально то шустро, а по сети - болт.
|
|||
40
kiruha
10.12.12
✎
14:29
|
(33)Можно малость быстрее
если известно, какие типы документов двигают регистр (как в 8) то можно через индекс IDDOCDEF,DATE,TIME,IDDOC jrn.IDDOCDEF+DTOS(jrn.date)+jrn.time+jrn.iddoc BETWEEN $ВидДокумента.РасходнаяНакладная+Dtos(Date(2012,12,1)) + ' ' AND $ВидДокумента.РасходнаяНакладная+Dtos(Date(2012,12,10)) + 'ZZZZZZZZZZZZZZZ' OR jrn.IDDOCDEF+DTOS(jrn.date)+jrn.time+jrn.iddoc BETWEEN $ВидДокумента.ПриходнаяНакладная+Dtos(Date(2012,12,1)) + ' ' AND $ВидДокумента.ПриходнаяНакладная+Dtos(Date(2012,12,10)) + 'ZZZZZZZZZZZZZZZ' OR jrn.IDDOCDEF+DTOS(jrn.date)+jrn.time+jrn.iddoc BETWEEN $ВидДокумента.Перемещение+Dtos(Date(2012,12,1)) + ' ' AND $ВидДокумента.Перемещение+Dtos(Date(2012,12,10)) + 'ZZZZZZZZZZZZZZZ' P.S> Если включена опция ОлеДБКоманда.Выполнить("EXECSCRIPT('SET ANSI OFF')"); то запись выглядит изящнее jrn.IDDOCDEF+DTOS(jrn.date)+jrn.time+jrn.iddoc =$ВидДокумента.РасходнаяНакладная+Dtos(Date(2012,12,1)) |
|||
41
Ёпрст
гуру
10.12.12
✎
14:33
|
(40) тогда уж.. лучше нужные виды в журнал запихать и потом через индекс IDJOURNAL,DATE,TIME,IDDOC
:) хотя проще, галку на регистр воткнуть |
|||
42
orefkov
10.12.12
✎
14:45
|
(39)
Потому что на самом деле унутре для доступа к данным используется тот же родной 1Сный движок, sqlite только высокоуровневая обертка вокруг вызовов seek, scan и т.д. Т.е. все те причины, которые вызывают тормоза 1С пр работе по сети, применимы и к 1sqlite. |
|||
43
Дык ё
10.12.12
✎
15:08
|
(36) ВыполнятьВТранзакции - уже, ОстаткиТоваровФр - попробую, спасибо. а что кешируется в том кеше, который PRAGMA cache_size? его увеличение дало небольшой (~5%) профит
прикрутить ИТЗ - не вопрос. вопрос - переходить на 1sqlite или нет? при текущих сравнительных показателях производительности получается - нет. а хочется. ветка создана в надежде на то, что я чего-то не учитываю :-( |
|||
44
orefkov
10.12.12
✎
15:49
|
(43)
В том кэше лежат данные самого sqlite, данные из виртуальных таблиц туда не попадают. Вернее, могут попасть уже на этапе сортировки. Так что скорее всего, большая часть расходов у тебя - передача по сети. |
|||
45
orefkov
10.12.12
✎
15:50
|
Попробуй сравни время без кучи left join'ов и order by, будет ли выигрыш.
|
|||
46
Кирпич
10.12.12
✎
16:09
|
(0) если ты к vfp через ado подключаешься, то оно у тебя работает в режиме клиент-сервер, т.е. запрос на сервере выполняется. наверное по этому и быстрее.
|
|||
47
Дык ё
10.12.12
✎
16:55
|
(44) есть методические рекомендации по уменьшению этих расходов?
(45) есть выигрыш. без джойнов 1sqlite всего в 4 раза медленнее, чем vfpoledb с джойнами :-) |
|||
48
Ёпрст
гуру
10.12.12
✎
16:59
|
(47) а индекс на табличку движений добавить и сравнить.. не ?
:) |
|||
49
kiruha
10.12.12
✎
18:12
|
(47)
4 года назад >> SqlLite не строит вспомогательные индексы при группировках и Order By и т.д.<< Т.е. сохранив во временную и проиндексировав на больших табличках можно добиться ускорения |
|||
50
orefkov
10.12.12
✎
21:15
|
(49)
Как раз таки строит. Сортировка при отсутствии индекса делается укладывались в неявную врем.таблицу с индексом по сортируемым полям и с дальнейшим проходом по ней по этому индексу. Для группировки - во время такого прохода наворачиваются итоги. |
|||
51
orefkov
10.12.12
✎
21:15
|
(47)
Расход памяти сравнивал? |
|||
52
Дык ё
13.12.12
✎
09:50
|
(51) нет, а зачем?
похоже, 1sqlite совсем не умеет в кеширование. добавление в запрос таблицы, котора там уже есть, заметно увеличивает время выполнения. на vfpoledb этого не наблюдается. отдельно доставляет scan table в планах выполнения на таблицах 1с, хотя на родных таблицах в аналогичных запросах выполняется ожидаемый search table. но тут не могу сказать, на сколько это плохо - не знаю, как оно там устроено внутри |
|||
53
Ёпрст
гуру
13.12.12
✎
09:57
|
(52) дык, можешь же явно индекс указать в тексте, тоже скан ?
|
|||
54
Ёпрст
гуру
13.12.12
✎
09:58
|
а ё.. вижу, и так указан у тебя в запросе .idx_.....
|
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |