Форум » LetoDB, HbNetio. » А работает ли механизм транзакций letodb » Ответить

А работает ли механизм транзакций letodb

PSP: в udf-функциях?

Ответов - 44, стр: 1 2 3 All

Pasha: Все равно у меня не получается медленная транзакция Без транзакции результат 24.65 сек С транзакцией: 4.96 сек Служба letodb установлена на компьютере с win7 letodb.ini: DataPath = e:/ EnableFileFunc = 1 EnableAnyExt = 1 Optimize = 1 AutOrder = 1 Default_Driver = NTX #Share_Tables = 1 Вот мой тест: PROC Main Local cPath, nSec, i, nn := 0 Local cNm := 'doma' Local lTr := .t. Field Code, OCATD, GNINMB, ID, Name request leto, DBFCDX RddSetDefault ("LETO") cPath := "//10.0.0.1:2812/" //cPath := "//127.0.0.1:2812/" Leto_Connect (cPath) USE (cPath + cNm) alias db_srv SHARED NEW if ! leto_File(cPath+cNm+'1.ntx') ? 'Indexing...' index on ID to doma1 index on Upper(NAME) to doma2 index on ID to doma3 endif SET INDEX TO (cPath + cNm + '1') additive SET INDEX TO (cPath + cNm + '2') additive SET INDEX TO (cPath + cNm + '3') additive dbSetOrder(1) use (cNm) alias db_loc new via "DBFCDX" go top nSec := Seconds() if lTr db_srv->(leto_BeginTransaction(32768)) endif while ! eof() db_srv->(dbAppend()) for i := 1 to fcount() db_srv->(FieldPut(i, db_loc->(FieldGet(i)))) next if nn % 10000 == 0 ? nn if lTr db_srv->(leto_CommitTransaction()) db_srv->(leto_BeginTransaction(32768)) endif endif if ++nn == 15000 exit endif skip enddo if lTr db_srv->(leto_CommitTransaction()) endif ? lTr, Seconds() - nSec RETURN

nbatocanin: Очень странно. Паша, я тестировал вашу программу на трех разных серверах (Win 2003, Win 7, Win 2012), и получил следующие результаты: [pre] Tr NoTr ------------------ s1 12.3 6.7 s2 8.4 6.2 s3 14.3 5.1 [/pre] Я бы попросить кого-нибудь, чтобы попробовать программу - на этом адресе тестовая программа: testhttps://drive.google.com/file/d/0BwEGIJ1QfjrKS1RYaEFGMXB0QzA/view?usp=sharing

Andrey: nbatocanin пишет: чтобы попробовать программу Попробовал. Сервер в инете Win2008, вот результат: Indexing... 0 10000 .F. 322.13 Indexing... 0 10000 .T. 2.36

nbatocanin: Есть ли функция Leto_CommitTransaction выполняет COMMIT? Необходимо ли выполнить COMMIT после Leto_CommitTransaction? Ненад

Pasha: COMMIT желательно делать до выполнения Leto_CommitTransaction()

nbatocanin: Я сделал новые тесты на несколько серверов (10+). Сначала я попробовал тест, который сделал Паша. Результаты (для меня) были очень странные. Время выполнения очень меняется (почему я взял среднее значение из нескольких тестов). На некоторых серверах, программа выполняется быстрее без транзакции, но в некоторых наоборот. Я думаю, время зависит от скорости диска и Windows кэширования. Например, тест на одном сервере с двумя дисками (HDD и SSD): [pre2] Tran NoTr --------------- HDD 3.9 1.1 SDD 1.4 1.8 [/pre2] Но этот тест не выполняют COMMIT в конце программы, так что я сделал новый тест, который использует функцию Leto_Commit(): [pre2]IF lTrans Leto_CommitTransaction() END IF Leto_Commit() [/pre2] Я также сделал тест так, чтобы больше соответствовать реальной ситуации. Вот тестовая программа: GoogleDrivehttps://drive.google.com/open?id=0BwEGIJ1QfjrKT2RLdlNvV2NwUHc Новый тест показал, что работать с транзакции (+COMMIT) всегда быстрее, чем без: [pre2] Tran NoTr --------------- S1 2.5 8.2 S2 1.1 5.6 S3 4.6 10.6 S4 1.1 0.8 [/pre2] Исключением является сервер с SSD (S4).

nbatocanin: Как ускорить транзакциу, которая имеет команду DELETE?. Например: [pre2]Leto_BeginTransaction() // SEEK nOldId WHILE nOldId == d_id DELETE SKIP END DO // ... // Leto_CommitTransaction()[/pre2] Эта программа работает в 20 раз быстрее без транзакции. Программа исключить около 25.000 записей.

Dima: nbatocanin пишет: WHILE nOldId == d_id Про ускорение не скажу а вот код надо подправить. [pre2] IF DBSEEK( nOldId ) WHILE nOldId == d_id .and. !eof() DELETE SKIP END DO ENDIF [/pre2] Хотя можно ускорить так (без проверки ключа) [pre2] IF DBSEEK( nOldId ) dbOrderInfo(DBOI_SCOPEBOTTOM,,,nOldId)) DO WHILE !eof() DELETE SKIP END DO dbOrderInfo(DBOI_SCOPEBOTTOMCLEAR) ENDIF [/pre2]

nbatocanin: Попробовал, но не имеют никакого эффекта. Я также попробовал DELETE WHILE. Без транзакции: 1.67 С транзакцией: 80.00

Pasha: nbatocanin пишет: Как ускорить транзакциу, которая имеет команду DELETE?. Например: Leto_BeginTransaction() // SEEK nOldId WHILE nOldId == d_id DELETE SKIP END DO // ... // Leto_CommitTransaction() Эта программа работает в 20 раз быстрее без транзакции. Программа исключить около 25.000 записей. Немного видоизмените алгоритм: Leto_BeginTransaction() // i := 0 SEEK nOldId WHILE nOldId == d_id DELETE i ++ if i%1000 == 0 Leto_CommitTransaction() Leto_BeginTransaction() endif SKIP END DO Leto_CommitTransaction() Причина замедления транзакции для большого количества записей следующая: после получения новых данных с сервера по команде skip выполняется проверка, есть ли новая полученная запись в данных транзакции. Если запись есть, то она формируется по данным из буфера транзакции. После каждой итерации буфер транзакции увеличивается, и проверка выполняется каждый раз медленнее. В этом случае такая проверка и не нужна, поскольку новая запись заведомо не присутствует в буфере транзакции, но в общем случае она нужна.

nbatocanin: Спасибо Пашa, это частично решило проблему. Но программа без транзакции по-прежнему работает быстрее (4.5sek; Без: 1.5сек). Можно ли как-то исключить эту проверку?

nbatocanin: Pasha пишет: Причина замедления транзакции для большого количества записей следующая: после получения новых данных с сервера по команде skip выполняется проверка, есть ли новая полученная запись в данных транзакции. Если запись есть, то она формируется по данным из буфера транзакции. После каждой итерации буфер транзакции увеличивается, и проверка выполняется каждый раз медленнее. В этом случае такая проверка и не нужна, поскольку новая запись заведомо не присутствует в буфере транзакции, но в общем случае она нужна. Паша, можно ли как-то выключение этой проверки? У меня есть большие транзакции, в которых нет дубликатов. Спасибо, Ненад

Pasha: Сегодня вечером сделаю обновление

SergKis: Pasha В старой версии leto (клиент), мы сделали (стало надежнее, стабильнее):[pre2] static BOOL lNewCritSect=TRUE; CRITICAL_SECTION CritSect; #define CS_EN() EnterCriticalSection( &CritSect ) #define CS_LV() LeaveCriticalSection( &CritSect ) long int leto_DataSendRecv( LETOCONNECTION * pConnection, const char * sData, ULONG ulLen ) { long int n = 0; if( lNewCritSect ) { InitializeCriticalSectionAndSpinCount(&CritSect, 0x00000400); // TryEnterCriticalSection( &CritSect ); lNewCritSect = FALSE; } CS_EN(); if( hb_ipSend( pConnection->hSocket, sData, (ulLen)? ulLen:strlen(sData), -1 ) > 0 ) { n = leto_Recv( pConnection->hSocket ); // return 0; } CS_LV(); // return leto_Recv( pConnection->hSocket ); return n; } [/pre2] в новой также планируем сделать, пока на новой не работаем (только тестируем)

SergKis: PS что то я с разделом промахнулся - это (выше) к "Internal Error" относиться. Sory

nbatocanin: long int leto_DataSendRecv( LETOCONNECTION * pConnection, const char * sData, ULONG ulLen ) Можете ли вы объяснить, что делает эта функция?

SergKis: nbatocanin пишет:что делает эта функция? как я понимаю, она посылает команды серверу и ждет их выполнения

nbatocanin: Pasha пишет: Сегодня вечером сделаю обновление работает, спасибо!

nbatocanin: Почему это не работает? USE Test NEW Leto_BeginTransaction () s := Select() FLock() (s)->(DBUnlock()) // Syntax error Leto_CommitTransaction ()

Pasha: Во время транзакции нельзя выдавать dbUnlock() Надо или разблокировать данные после LETO_COMMITTRANSACTION(). либо выдать LETO_COMMITTRANSACTION(.t.), задав параметр lUnlockAll



полная версия страницы