Sql server VBScript-在SQL Server中将SHA1存储为数字或二进制值

Sql server VBScript-在SQL Server中将SHA1存储为数字或二进制值,sql-server,vbscript,asp-classic,sha1,Sql Server,Vbscript,Asp Classic,Sha1,我目前正在SQL Server中将我的SHA1值存储为char(40)。我的印象是,我可以通过将此字段更改为数值来提高查找速度。但是,我不确定使用什么字段/数据类型将其存储在SQL Server中,以及如何在VBScript中转换它。我应该使用数字还是十进制?我需要使用多少位数 我在某个地方读到过,建议使用二进制(20)。然而,在VBScript中使用二进制值似乎并不太容易,所以我假设使用数值会更好 目前这是我的SHA1函数。我将它返回的字符串值存储在数据库的my char(40)字段中,并使用

我目前正在SQL Server中将我的SHA1值存储为char(40)。我的印象是,我可以通过将此字段更改为数值来提高查找速度。但是,我不确定使用什么字段/数据类型将其存储在SQL Server中,以及如何在VBScript中转换它。我应该使用数字还是十进制?我需要使用多少位数

我在某个地方读到过,建议使用二进制(20)。然而,在VBScript中使用二进制值似乎并不太容易,所以我假设使用数值会更好

目前这是我的SHA1函数。我将它返回的字符串值存储在数据库的my char(40)字段中,并使用下面的第二位代码执行查找

Private Function SHA1(s)
    Dim asc, enc, bytes, outstr, pos
    Set asc = CreateObject("System.Text.UTF8Encoding")
    Set enc = CreateObject("System.Security.Cryptography.SHA1CryptoServiceProvider")
    'Convert the string to a byte array and hash it
    bytes = asc.GetBytes_4(s) 'This is how you use .Net overloaded methods in VBScript
    bytes = enc.ComputeHash_2((bytes))
    outstr = ""
    'Convert the byte array to a hex string
    For pos = 1 To Lenb(bytes)
        outstr = outstr & LCase(Right("0" & Hex(Ascb(Midb(bytes, pos, 1))), 2))
    Next
    SHA1 = outstr
    Set asc = Nothing
    Set enc = Nothing
End Function
这是我的查找函数。它已经运行得很快了,但我正在寻找任何可以优化代码的方法。如果我真的使用二进制来存储数据,那么我在查找数据时也必须使用它。我想我可能会使用存储过程,它允许我使用SQL Server函数进行来回转换。也许那是一条更好的路线。请告知

Function GetHTTPRefererIDBySHA1(s)
    Dim r
    Set r = Server.CreateObject("ADODB.Recordset")      
    r.open "SELECT httprefererid FROM httpreferer " & _
            "WHERE sha1 = '" & s & "'", con, adOpenForwardOnly, adLockReadOnly
    If Not (r.eof and r.bof) then
        GetHTTPRefererIDBySHA1 = r("httprefererid")
    End If
    r.close
    set r = nothing
End Function
编辑:
多亏了ScottE和Google,我的查询速度明显加快了。以下是有关我的解决方案的一些信息。
1) 我创建了一个名为SHA1Bin的字段。这是一个二进制(20)类型的字段。
2) 插入新记录时,我使用存储过程。因为我不太关心空间,所以我将原始httpreferer值和它的SHA1二进制值保存在同一个表和同一行中。我的存储过程使用HashBytes函数将原始值转换为SHA1二进制文件(SQL Server 2008)。
3) VBScript中的SHA1函数与上面的相同,但我现在在查找时使用它。下面是GetReferer函数的修改版本:

Function GetHTTPRefererIDBySHA1(s)
    Dim r
    Set r = Server.CreateObject("ADODB.Recordset")      
    r.open "SELECT httprefererid FROM httpreferer WHERE " & _
            "sha1bin = CONVERT(binary(20), 0x" & SHA1(s) & ")", _
            tcon, adOpenForwardOnly, adLockReadOnly

    If Not (r.eof and r.bof) then
        GetHTTPRefererIDBySHA1 = r("httprefererid")
    Else
        '//Insert new record code intentionally omitted
    End If
    r.close
    set r = nothing
End Function

我认为你的思路相对正确;然而,你可以做一些事情来加快这一速度

SHA1背景 无论你在哪里读到的,使用二进制(20)都是非常死板的。SHA1是一个160位的消息(20字节),我们通常以原始格式处理它——正如您已经知道的那样,因为您的函数将原始二进制文件转换为字符串

转换为数字 所以不管怎样,20字节就是20字节。您不能将其转换为其他内容以使其在数据库中执行得更快。尝试将其转换为数字将不成功,因为您将获得算术溢出错误(数字仅具有17字节的空间)

如何让它变得更好 你已经完成了一半的战斗。如果在VBScript中更易于使用,则可以将数据保留为字符数据类型。或者,您可以将其存储为二进制文件(20);这是我在数据仓库项目中采用的方法。如果要将其保留为字符串,请将其设置为CHAR(20)而不是CHAR(40)。CHAR数据类型存储指定的字节数,即使其中一半是空的(对您来说几乎就是这样)。这里的一个“gotcha”是,您的函数将在字符串前面呈现一个“0x…”,从技术上讲,它不是值的一部分,但在构造SQL语句时,它是指示值是二进制的必要条件。因此,您可以使用CHAR(22)或在必要时进行连接。在这两种情况下,通过减少字段定义中的字符数,SQL执行更少的读取来获取数据,这将加快速度。另一种数据类型的替代方法是VARCHAR,它将修剪字符串末尾的空白(同样,读取次数越少,查询越愉快)

除此之外,索引它就像你做的那样。如果您还没有这样做,请在SHA1列上创建一个索引,并在索引中包含httprefererid,您的查询将仅使用该索引进行选择,并且将是最快的,因为只读取了所需的数据元素。这称为a(因为它涵盖了过滤器和选定列)。该索引将类似于:

在dbo.httpreferer(sha1)include(httprefererid)上创建索引ix\u httpreferer\u sha1


希望有帮助

愚蠢的问题-你索引了sha1列了吗?是的,我已经索引了。这并不是说它表现得很慢。我只是假设通过使用更高效的存储/查找,它可以执行得更好。你提到我应该使用CHAR(20)而不是CHAR(40)。如果我理解正确,我的SHA1函数实际上返回一个40字符的ascii/十六进制。为了把它减少到20字节,我必须使用其他格式。我是否可以将名为bytes的20字节变量转换为这20个字节的ascii表示形式?如果理解正确的话,其中一个问题是chr(0)的任何出现都会导致my string变量终止。我有一个想法,但我没有尝试过,就是将20字节数组作为二进制(20)直接存储到数据库中,但我不确定如何对其进行查询。