背景故事
我在Android客户端的后端工作。有很多数据要显示,需要一些离线功能,所以我必须解决同步问题。所述数据由临时表组成。
我们的解决方案
现在,为了让客户端知道可能的更改而不执行完整的客户端数据库擦除和创建(花费大量时间),我为每个临时表创建了一个哈希行。通过获取临时表行,为其创建JSON,然后从该JSON中创建散列来创建所述散列。它正在发挥作用。
我对此解决方案的问题
我认为这不是理想的解决方案。所有这些操作看起来都很苛刻,从我的测试中可以看出:
我想要什么
如果我们做错了什么,我感兴趣。这个问题有更好的解决方案吗?是否有不太苛刻的方法来创建每个临时表记录的哈希值?
我们目前正在使用 OpenEdge 10.2B 。
负责哈希创建的程序, create_hash 创建widget-pool。
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.
我想要什么
答案 0 :(得分:4)
这是你的哈希值的近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字段和单个记录的辅助临时表,因为缓冲区对象句柄的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 .
我还没有尝试优化您的代码。
如果我们做错了什么,我感兴趣。这个问题有更好的解决方案吗?是否有不太苛刻的方法来创建每个临时表记录的哈希值?
运行时的很大一部分将来自为每条记录创建动态临时表 - 我怀疑你需要一遍又一遍地为每条记录创建临时表。
也许,通过移动这部分
create temp-table ttDynamic.
ttDynamic:add-fields-from(inp_hBuffer).
ttDynamic:temp-table-prepare(inp_hBuffer:table).
在哈希过程之外,您的代码也将得到改进。但我怀疑它会比基于RAW-TRANSFER方法的版本更快。
答案 1 :(得分:0)
(代表OP发布)。
我实施了迈克建议的解决方案。对于我们的结构,我无法按照建议在程序之外移动帮助程序内容。在实现我的现实世界问题并测量整个过程的时间之后,通过2450次调用,我获得了2054ms的先前解决方案,而迈克的解决方案只需要240ms。这意味着我无法在现实世界的实施中获得全部收益,但即便快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)).
根据迈克的建议(临时表定义和创建仅调用一次),我们终于有时间进一步优化它,现在它甚至更快。我真的不明白为什么临时表定义,但主要是创建一个记录,是“慢”。
另请注意,raw-transfer
方法不适用于大于32kB的字段。