散列 temp-table 行

Hash a temp-table row

背景故事

我在 Android 客户的后端工作。需要展示的数据很多,需要一些离线功能,所以要解决同步问题。所述数据由temp-tables.

组成

我们的解决方案

现在,为了让客户端知道可能的更改,而不是强制执行完整的客户端数据库擦除和创建(需要很多时间),我对每个进行了 hash temp-table 行。所述哈希是通过获取 temp-table 行创建的,为其创建一个 JSON,然后从该 JSON 中创建一个哈希。正在运行。

我对这个解决方案的问题

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

我想要什么

如果我们做错了什么,我很感兴趣。这个问题有更好的解决方案吗?从每个单独的 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.

我想要的

这是一个几乎快 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 的字段。