当使用CHECKSUM列类型人为地创建哈希索引时,查找实际上是O(1)还是O(lg n),就像它是聚簇索引一样?我有一个表,我将根据其ID列进行选择,我需要尽可能快地查找,因此聚簇索引是最快的选择吗?我正在寻找能提供O(1)表现的东西。
答案 0 :(得分:12)
好的,2分
SQL CHECKSUM函数不会产生哈希值。它实际上计算CRC值。基于哈希检查不是一个非常好的候选者,因为会有相对大量的冲突。如果需要哈希函数,则应检查hash_bytes函数
其次,您实际上并没有创建哈希索引。您正在哈希值上创建一个普通的b树,因此查找时间与类似大小的数据类型上的任何其他b树索引完全相同。
有可能通过使用CRC或长varchar值的散列来获得一点性能,以允许比较较少数量的字节,但字符串比较只检查所需的字节数,这是至于第一个不匹配的字符,如果匹配散列值,则需要仔细检查实际值。因此,除非你有很多非常相似的字符串,否则你最终可能会使用hash(或CRC)来比较MORE字节。
简而言之,我认为这不是一个合理的计划,但与所有优化一样,您应该在特定情况下进行测试然后再做出决定。如果您愿意发布它们,我会很有兴趣看到您的结果。而且我不相信在SQL服务器中找到一行比使用聚簇索引有更快的方法
如果你关心,Ingres(由CA)可以创建哈希索引,然后获得O(1)。可能还有其他RDBM也支持真正的哈希索引。
答案 1 :(得分:6)
我认为SQL服务器本身没有基于哈希表的索引。 BOL documentation正在谈论在计算值上构建标准(树)索引。这与Linear Hash Table不同,this blog post是某些DBMS平台上可用的索引结构,但不是SQL Server(AFAIK)。
使用{{3}}中描述的技术来散列大字符串值(例如URL)以获得更快的查找效果,您可能会从中受益。但是,底层索引仍然是树结构,并且是O(Log N)。
答案 2 :(得分:1)
您可以尝试设置使用散列连接,您可以查看执行计划以验证实际使用散列连接。使用散列连接时,SQL Server仍将首先构建散列表,作为执行单个查询的一部分。我相信索引永远不会存储为哈希,只能存储为树。
一般情况下,我不会创建一个人工哈希列,除非你正在对潜在的大字符串或二进制blob进行精确匹配(如pipTheGeek所提到的)。我只想补充说,有时这是必要的,因为字符串可能太大而无法放入索引键。对于SQL Server,我认为2k的索引键的大小是有限制的。
当然,在您的连接中,您需要包含哈希列和源列,以解决由哈希引起的任何歧义。
答案 3 :(得分:0)
如果ID字段是int,则在ID字段上搜索聚簇索引的索引CHECKSUM没有任何优势,因为两者都将进行聚簇索引搜索。此外,int列的CHECKSUM始终返回与列相同的值(即CHECKSUM(535)= 535)。但是,如果ID是长字符列,则CHECKSUM查找通常会执行得更好。