散列 temp-table 行
Hash a temp-table row
背景故事
我在 Android 客户的后端工作。需要展示的数据很多,需要一些离线功能,所以要解决同步问题。所述数据由temp-tables.
组成
我们的解决方案
现在,为了让客户端知道可能的更改,而不是强制执行完整的客户端数据库擦除和创建(需要很多时间),我对每个进行了 hash temp-table 行。所述哈希是通过获取 temp-table 行创建的,为其创建一个 JSON,然后从该 JSON 中创建一个哈希。正在运行。
我对这个解决方案的问题
我认为这不是理想的解决方案。所有这些操作看起来要求很高,根据我的测试,它显示:
- 对于每个数据;基线,无动作 = 90 毫秒
- 填充一个 temp-table 里面每个 buffer-copy = 400 ms
- 在for each = 2 880 ms
内的人口后,用上述解决方案计算散列
我想要什么
如果我们做错了什么,我很感兴趣。这个问题有更好的解决方案吗?从每个单独的 temp-table 记录中创建散列的要求是否较低?
我们目前正在使用 OpenEdge 10.2B。
负责哈希创建的过程,create_hash
创建小部件池。
define input parameter inp_hBuffer as handle no-undo.
define output parameter out_cHash as c no-undo.
define var ttDynamic as handle no-undo.
define var hBufferTT as handle no-undo.
define var lResult as l no-undo.
define var cDataTT as longchar no-undo.
define var itime as i.
do on error undo,return error:
if not(valid-handle(inp_hBuffer) and inp_hBuffer:type = 'BUFFER':u) then
return error substitute('Neplatny typ vstupniho parametru predaneho procedure "&1".','m_ghashb':u).
create temp-table ttDynamic.
ttDynamic:add-fields-from(inp_hBuffer).
ttDynamic:temp-table-prepare(inp_hBuffer:table).
hBufferTT = ttDynamic:default-buffer-handle.
hBufferTT:buffer-copy(inp_hBuffer).
ttDynamic:write-json('longchar':u,cDataTT).
out_cHash = hex-encode(md5-digest(cDataTT)).
end.
return.
及其用法
for first lbUsrtab where
lbUsrtab.ucje = GetUcje('m_usrtab':U) and
lbUsrtab.login-name = LoginName no-lock,
each lbWcesta where
lbWcesta.ucje = GetUcje('wcesta':U) and
lbWcesta.kodu = lbUsrtab.kodu no-lock,
each lbWciorg where
lbWciorg.ucje = GetUcje('wciorg':U) and
lbWciorg.cest = lbWcesta.cest no-lock,
each lbKontaktr where
lbKontaktr.ucje = GetUcje('kontaktr':U) and
lbKontaktr.corg = lbWciorg.corg no-lock
by lbKontaktr.zako descending
on error undo, return error return-value:
create ttKontaktr.
buffer-copy lbKontaktr to ttKontaktr.
run create_hash(input buffer ttKontaktr:handle, output ttKontaktr.hash).
end.
我想要的
- 要知道我们是否做错了什么,出于某种原因,这个解决方案对我来说并不合适,我相信有人也必须面对这个问题(创建一个临时哈希值-table)
- 确实要花很多时间,以后应该会有问题,所以我想尽快解决这个问题
这是一个几乎快 20 倍的哈希解决方案(对于 1000 次调用,它是 320 毫秒对 17 毫秒):
PROCEDURE hash2:
DEFINE INPUT PARAMETER inp_hBuffer AS HANDLE NO-UNDO .
DEFINE OUTPUT PARAMETER out_cHash AS CHARACTER NO-UNDO .
inp_hBuffer:RAW-TRANSFER (TRUE, hRawField) .
out_cHash = HEX-ENCODE (MD5-DIGEST (ttWithRaw.raw_field)).
END PROCEDURE .
您将需要一个带有 RAW 字段和单个记录的助手 temp-table,因为缓冲区对象句柄的 RAW-TRANSFER 方法仅适用于缓冲区字段对象句柄,所以有这样的东西在 hash2 过程之外,你只需要 运行 它一次:
DEFINE VARIABLE hRawField AS HANDLE NO-UNDO.
DEFINE TEMP-TABLE ttWithRaw NO-UNDO
FIELD raw_field AS RAW .
ASSIGN hRawField = BUFFER ttWithRaw:BUFFER-FIELD("raw_field") .
CREATE ttWithRaw .
我还没有尝试优化您的代码。
I am interested if we are doing something wrong. Is there a better solution for this problem? Is there less demanding way for creating hash out of each individual temp-table record?
运行时间的很大一部分将用于为每条记录创建动态临时文件-table - 我怀疑您是否需要创建该临时文件-table ] 一遍又一遍的每一条记录。
也许,通过移动这部分
create temp-table ttDynamic.
ttDynamic:add-fields-from(inp_hBuffer).
ttDynamic:temp-table-prepare(inp_hBuffer:table).
在散列过程之外,您的代码也会得到改进。然而,我怀疑它会比基于 RAW-TRANSFER 方法的版本更快。
(代表OP发帖).
解决方案
我实施了迈克建议的解决方案。对于我们的结构,我无法按照建议将辅助内容移到过程之外。在解决我的现实世界问题并测量整个过程的时间后,通过 2450 次调用,我得到 2054 毫秒的先前解决方案,而 Mike 的解决方案只需要 240 毫秒。这意味着我无法在现实世界的实施中获得全部好处,但即使是快 8.5 倍对我来说也很好。我会牢记所有这些,并在有时间时回来进一步优化。
这是我的程序的样子
DEFINE INPUT PARAMETER inp_hBuffer AS HANDLE NO-UNDO .
DEFINE OUTPUT PARAMETER out_cHash AS CHARACTER NO-UNDO .
DEFINE VARIABLE hRawField AS HANDLE NO-UNDO.
DEFINE TEMP-TABLE ttWithRaw NO-UNDO
FIELD raw_field AS RAW .
ASSIGN hRawField = BUFFER ttWithRaw:BUFFER-FIELD("raw_field") .
CREATE ttWithRaw .
inp_hBuffer:RAW-TRANSFER (TRUE, hRawField) .
out_cHash = HEX-ENCODE (MD5-DIGEST (ttWithRaw.raw_field)).
我们遇到的问题
我们终于有时间根据 Mike 的建议进一步优化它(temp-table 定义和创建仅调用一次),现在速度更快。我真的不明白为什么 temp-table 定义,但主要是记录的创建,是 "slow".
另请记住,raw-transfer
方法不适用于大于 32kB 的字段。
背景故事
我在 Android 客户的后端工作。需要展示的数据很多,需要一些离线功能,所以要解决同步问题。所述数据由temp-tables.
组成我们的解决方案
现在,为了让客户端知道可能的更改,而不是强制执行完整的客户端数据库擦除和创建(需要很多时间),我对每个进行了 hash temp-table 行。所述哈希是通过获取 temp-table 行创建的,为其创建一个 JSON,然后从该 JSON 中创建一个哈希。正在运行。
我对这个解决方案的问题
我认为这不是理想的解决方案。所有这些操作看起来要求很高,根据我的测试,它显示:
- 对于每个数据;基线,无动作 = 90 毫秒
- 填充一个 temp-table 里面每个 buffer-copy = 400 ms
- 在for each = 2 880 ms 内的人口后,用上述解决方案计算散列
我想要什么
如果我们做错了什么,我很感兴趣。这个问题有更好的解决方案吗?从每个单独的 temp-table 记录中创建散列的要求是否较低?
我们目前正在使用 OpenEdge 10.2B。
负责哈希创建的过程,create_hash 创建小部件池。
define input parameter inp_hBuffer as handle no-undo.
define output parameter out_cHash as c no-undo.
define var ttDynamic as handle no-undo.
define var hBufferTT as handle no-undo.
define var lResult as l no-undo.
define var cDataTT as longchar no-undo.
define var itime as i.
do on error undo,return error:
if not(valid-handle(inp_hBuffer) and inp_hBuffer:type = 'BUFFER':u) then
return error substitute('Neplatny typ vstupniho parametru predaneho procedure "&1".','m_ghashb':u).
create temp-table ttDynamic.
ttDynamic:add-fields-from(inp_hBuffer).
ttDynamic:temp-table-prepare(inp_hBuffer:table).
hBufferTT = ttDynamic:default-buffer-handle.
hBufferTT:buffer-copy(inp_hBuffer).
ttDynamic:write-json('longchar':u,cDataTT).
out_cHash = hex-encode(md5-digest(cDataTT)).
end.
return.
及其用法
for first lbUsrtab where
lbUsrtab.ucje = GetUcje('m_usrtab':U) and
lbUsrtab.login-name = LoginName no-lock,
each lbWcesta where
lbWcesta.ucje = GetUcje('wcesta':U) and
lbWcesta.kodu = lbUsrtab.kodu no-lock,
each lbWciorg where
lbWciorg.ucje = GetUcje('wciorg':U) and
lbWciorg.cest = lbWcesta.cest no-lock,
each lbKontaktr where
lbKontaktr.ucje = GetUcje('kontaktr':U) and
lbKontaktr.corg = lbWciorg.corg no-lock
by lbKontaktr.zako descending
on error undo, return error return-value:
create ttKontaktr.
buffer-copy lbKontaktr to ttKontaktr.
run create_hash(input buffer ttKontaktr:handle, output ttKontaktr.hash).
end.
我想要的
- 要知道我们是否做错了什么,出于某种原因,这个解决方案对我来说并不合适,我相信有人也必须面对这个问题(创建一个临时哈希值-table)
- 确实要花很多时间,以后应该会有问题,所以我想尽快解决这个问题
这是一个几乎快 20 倍的哈希解决方案(对于 1000 次调用,它是 320 毫秒对 17 毫秒):
PROCEDURE hash2:
DEFINE INPUT PARAMETER inp_hBuffer AS HANDLE NO-UNDO .
DEFINE OUTPUT PARAMETER out_cHash AS CHARACTER NO-UNDO .
inp_hBuffer:RAW-TRANSFER (TRUE, hRawField) .
out_cHash = HEX-ENCODE (MD5-DIGEST (ttWithRaw.raw_field)).
END PROCEDURE .
您将需要一个带有 RAW 字段和单个记录的助手 temp-table,因为缓冲区对象句柄的 RAW-TRANSFER 方法仅适用于缓冲区字段对象句柄,所以有这样的东西在 hash2 过程之外,你只需要 运行 它一次:
DEFINE VARIABLE hRawField AS HANDLE NO-UNDO.
DEFINE TEMP-TABLE ttWithRaw NO-UNDO
FIELD raw_field AS RAW .
ASSIGN hRawField = BUFFER ttWithRaw:BUFFER-FIELD("raw_field") .
CREATE ttWithRaw .
我还没有尝试优化您的代码。
I am interested if we are doing something wrong. Is there a better solution for this problem? Is there less demanding way for creating hash out of each individual temp-table record?
运行时间的很大一部分将用于为每条记录创建动态临时文件-table - 我怀疑您是否需要创建该临时文件-table ] 一遍又一遍的每一条记录。
也许,通过移动这部分
create temp-table ttDynamic.
ttDynamic:add-fields-from(inp_hBuffer).
ttDynamic:temp-table-prepare(inp_hBuffer:table).
在散列过程之外,您的代码也会得到改进。然而,我怀疑它会比基于 RAW-TRANSFER 方法的版本更快。
(代表OP发帖).
解决方案
我实施了迈克建议的解决方案。对于我们的结构,我无法按照建议将辅助内容移到过程之外。在解决我的现实世界问题并测量整个过程的时间后,通过 2450 次调用,我得到 2054 毫秒的先前解决方案,而 Mike 的解决方案只需要 240 毫秒。这意味着我无法在现实世界的实施中获得全部好处,但即使是快 8.5 倍对我来说也很好。我会牢记所有这些,并在有时间时回来进一步优化。
这是我的程序的样子
DEFINE INPUT PARAMETER inp_hBuffer AS HANDLE NO-UNDO .
DEFINE OUTPUT PARAMETER out_cHash AS CHARACTER NO-UNDO .
DEFINE VARIABLE hRawField AS HANDLE NO-UNDO.
DEFINE TEMP-TABLE ttWithRaw NO-UNDO
FIELD raw_field AS RAW .
ASSIGN hRawField = BUFFER ttWithRaw:BUFFER-FIELD("raw_field") .
CREATE ttWithRaw .
inp_hBuffer:RAW-TRANSFER (TRUE, hRawField) .
out_cHash = HEX-ENCODE (MD5-DIGEST (ttWithRaw.raw_field)).
我们遇到的问题
我们终于有时间根据 Mike 的建议进一步优化它(temp-table 定义和创建仅调用一次),现在速度更快。我真的不明白为什么 temp-table 定义,但主要是记录的创建,是 "slow".
另请记住,raw-transfer
方法不适用于大于 32kB 的字段。