如何使用 linq2db 在 C# 中使用 md5 oracle blob 进行哈希?

问题描述 投票:0回答:1

我想对oracle表的blob数据进行哈希处理。我看到了两个选择:使用 DBMS_CRYPTO 在数据库中执行此操作,或者编写一个处理器,该处理器将抛出所有 blob、获取流并使用 md5 对它们进行哈希处理。哈希本身将转到另一个表,该表具有指向将 blob 数据存储为文件内容的表的外键。有些文件超过 100mb。理论上我可以小批量处理它们,但即使我只处理批量大小 10,也不确定内存效率。 P.s 有近 20k blob 数据需要进行哈希处理

c# .net oracle linq2db
1个回答
0
投票

对 Oracle 表中的 BLOB 数据进行哈希处理有两种主要方法:使用 Oracle 的

DBMS_CRYPTO
包直接在数据库中执行此操作,或者编写一个外部处理器来读取 BLOB、对它们进行哈希处理(使用 MD5 之类的方法)并存储哈希值在一个单独的表中。每种方法都有其优点和缺点,因此最佳选择实际上取决于您优先考虑的内容 - 性能、内存效率或可扩展性。

选项 1:使用
DBMS_CRYPTO

对数据库中的 BLOB 进行哈希处理

优点:

  • 数据保留在数据库中:这会将所有内容保留在数据库中,从而最大程度地减少数据移动。
  • 很好地处理并发:Oracle 将为您管理并发访问,这简化了事情。
  • 快速实施:如果您熟悉 PL/SQL,则可以相当快地启动并运行它。

缺点:

  • 数据库负担过重:对大型 BLOB 进行哈希处理可能会占用大量资源,可能会降低数据库速度。
  • 可扩展性问题:如果您有非常大的 BLOB,此方法可能会将数据库的内存和 CPU 推向极限。
  • 锁定在 Oracle 中:这种方法是 Oracle 特有的,因此您只能遵循 Oracle 的做事方式。

PL/SQL 代码示例:

DECLARE
    v_hash_value RAW(32);
BEGIN
    FOR rec IN (SELECT id, blob_column FROM your_blob_table) LOOP
        v_hash_value := DBMS_CRYPTO.Hash(UTL_RAW.CAST_TO_RAW(rec.blob_column), DBMS_CRYPTO.HASH_MD5);
        
        INSERT INTO your_hash_table (id, hash_value)
        VALUES (rec.id, v_hash_value);
        
        COMMIT;
    END LOOP;
END;
/

选项 2:使用外部处理器对 BLOB 进行哈希处理

优点:

  • 更好的控制:您可以更好地控制正在使用的内存和 CPU 数量,这有助于提高可扩展性。
  • 横向扩展:如果需要,您可以将工作负载分散到多台计算机上。
  • 更灵活:您不受 Oracle 功能的限制;您可以使用任何您喜欢的哈希算法或工具。

缺点:

  • 更多数据移动:您需要从数据库中提取大型 BLOB,这可能会很慢并且占用资源。
  • 复杂性:与数据库内解决方案相比,这种方法需要更多的设置和维护。

C# 中的外部处理器示例:

using System;
using System.Data.OracleClient;
using System.Security.Cryptography;
using System.Text;

class Program
{
    static void Main()
    {
        string connString = "your_connection_string";
        using (var connection = new OracleConnection(connString))
        {
            connection.Open();
            var command = new OracleCommand("SELECT id, blob_column FROM your_blob_table", connection);
            var reader = command.ExecuteReader();

            while (reader.Read())
            {
                var id = reader["id"];
                var blob = reader["blob_column"] as byte[];

                if (blob != null)
                {
                    string hash = ComputeMD5Hash(blob);

                    var insertCommand = new OracleCommand("INSERT INTO your_hash_table (id, hash_value) VALUES (:id, :hash_value)", connection);
                    insertCommand.Parameters.Add(new OracleParameter("id", id));
                    insertCommand.Parameters.Add(new OracleParameter("hash_value", hash));
                    insertCommand.ExecuteNonQuery();
                }
            }
        }
    }

    static string ComputeMD5Hash(byte[] data)
    {
        using (var md5 = MD5.Create())
        {
            byte[] hashBytes = md5.ComputeHash(data);
            return BitConverter.ToString(hashBytes).Replace("-", "").ToLower();
        }
    }
}

内存效率技巧

  • 在数据库中:您可以使用 Oracle 的
    dbms_lob
    包以较小的块处理大 BLOB,这有助于管理内存使用情况。
  • 在外部处理器中:上面的C#代码可以调整为以更小的段读取BLOB数据,这也有助于提高内存效率。

结论

  • 为了简单:如果您想要一个简单的解决方案并且您的数据库可以处理负载,请在 Oracle 中使用
    DBMS_CRYPTO
  • 更多控制和可扩展性:如果您正在处理繁重的工作负载或需要更多控制,则外部处理器可能是更好的选择。它还为您可以使用的工具和算法提供了更大的灵活性。
© www.soinside.com 2019 - 2024. All rights reserved.