散列临时表行

vso*_*tka 2 progress-4gl openedge

背景故事

我负责 Android 客户端的后端工作。有很多数据要显示,还需要一些离线功能,所以必须解决同步问题。所述数据由临时表组成。

我们的解决方案

现在,为了让客户端了解可能的更改,而不是强制执行完整的客户端数据库擦除和创建(需要大量时间),我对每个临时表行进行了哈希处理。所述哈希值是通过获取临时表行、为其创建 JSON,然后从该 JSON 生成哈希值来创建的。这是工作。

我对这个解决方案的问题

我认为这不是理想的解决方案。所有这些操作看起来要求很高,从我的测试来看,它表明:

  • 对于每个数据都有一些数据;基线,无操作 = 90 毫秒
  • 在其中填充一个临时表,其中每个缓冲区复制 = 400 ms
  • 在 foreach = 2 880 ms 内的总体之后,使用上述解决方案计算哈希

我想要的是

我很感兴趣我们是否做错了什么。对于这个问题有更好的解决方案吗?是否有要求较低的方法来从每个单独的临时表记录中创建哈希?

我们目前使用的是OpenEdge 10.2B

程序负责hash创建,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.
Run Code Online (Sandbox Code Playgroud)

及其用途

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.
Run Code Online (Sandbox Code Playgroud)

我想要的是

  • 要知道我们是否做错了什么,由于某种原因,这个解决方案对我来说看起来不正确,并且我相信有人也必须面对这个问题(创建临时表的哈希值)
  • 这确实需要很多时间,并且将来应该会成为一个问题,所以我想尽早解决这个问题

Mik*_*ner 5

这是一个几乎快 20 倍的哈希解决方案(对于 1000 次调用,它是 320 毫秒 vs 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 .
Run Code Online (Sandbox Code Playgroud)

您需要一个带有 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 .
Run Code Online (Sandbox Code Playgroud)

我还没有尝试优化你的代码。

我很感兴趣我们是否做错了什么。对于这个问题有更好的解决方案吗?是否有要求较低的方法来从每个单独的临时表记录中创建哈希?

运行时的很大一部分将来自为每个记录创建动态临时表 - 我怀疑您是否需要一遍又一遍地为每个记录创建该临时表。

也许,通过移动这部分

   create temp-table ttDynamic.
   ttDynamic:add-fields-from(inp_hBuffer).
   ttDynamic:temp-table-prepare(inp_hBuffer:table).
Run Code Online (Sandbox Code Playgroud)

脱离了哈希过程,您的代码也会得到改进。但我怀疑它会比基于 RAW-TRANSFER 方法的版本更快。