I'm currently storing my SHA1 value in SQL Server as char(40). I'm under the impression that I could possible increase the speed of my lookups by changing this field to a numeric value. However, I'm uncertain of what field/data type to use to store this in SQL Server and how to convert it in VBScript. Should I use number or decimal and how many digits do I need to use?
I have read somewhere that using Binary(20) is recommended. However, working with Binary values in VBScript doesn't seem to be too easy so I'm assuming that I'll be better off using a numeric value instead.
Currently this is my SHA1 function. I store the string value it returns in my char(40) field in the database and perform my lookups using the second bit of code below.
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
Here's my lookup function. It operates quite quickly already but I'm looking for any way I can to optimize my code. If I do use binary to store the data I'm going to have to use it when I look it up too. I suppose I could possibly use stored procedures which would allow me to use SQL Server functions to convert back and forth. Maybe that would be a better route. Please advise.
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
Edit:
Thanks to ScottE and Google I was able to speed up my queries noticeably. Here's a little information on my solution.
1) I created a field called SHA1Bin. It's a field of type binary(20).
2) When I insert a new record I use a stored procedure. Because I'm not overly concerned about space, I save the raw httpreferer value and the SHA1 binary value of it in the same table and same row. My stored procedure converts the raw value to SHA1 binary using the HashBytes function (SQL Server 2008).
3) My SHA1 function in VBScript remains the same as above but I now use it when I do lookups. Here's a modified version of the GetReferer function:
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