哈希表如何工作?它比“SELECT * from ...”更快

时间:2009-02-12 06:48:58

标签: mysql hash hashtable

让我们说,我有:

Key | Indexes | Key-values
----+---------+------------
001 | 100001  | Alex
002 | 100002  | Micheal
003 | 100003  | Daniel

让我们说,我们想搜索001,如何使用哈希表进行快速搜索过程?

我们在mysql中使用“SELECT * from ..”是不是一样的?他们说,从头到尾搜索“SELECT *”很多,但哈希表不是吗?为什么以及如何?

通过使用哈希表,我们是否减少了我们正在搜索的记录?怎么样?

任何人都可以演示如何在mysql查询代码中插入和检索哈希表进程吗?例如,

SELECT * from table1 where hash_value="bla" ...

另一种情况: 如果索引类似于S0001,S0002,T0001,T0002等。在mysql中我可以使用:

SELECT * from table WHERE value = S*

是不是一样又快?

5 个答案:

答案 0 :(得分:12)

一个简单的哈希表通过将项保存在多个列表而不是一个列表上来工作。它使用非常快速且可重复(即非随机)的方法来选择保持每个项目的列表。因此,当需要再次找到该项时,它会重复该方法以发现要查找的列表,然后在该列表中进行正常(慢速)线性搜索。

通过将项目分成17个列表,搜索速度提高了17倍,这是一个很好的改进。

虽然当然只有列表长度大致相同时才会出现这种情况,因此选择一种在列表之间分配项目的好方法非常重要。

在您的示例表中,第一列是键,我们需要找到该项。我们假设我们将维护17个列表。要插入内容,我们对名为hashing的键执行操作。这只是将键变成一个数字。它不返回随机数,因为它必须始终为同一个键返回相同的数字。但与此同时,这些数字必须“广泛传播”。

然后我们取结果数并使用模数将其缩小到我们列表的大小:

Hash(key) % 17

这一切都发生得非常快。我们的列表是一个数组,所以:

_lists[Hash(key % 17)].Add(record);

然后,使用该键找到项目:

Record found = _lists[Hash(key % 17)].Find(key);

请注意,每个列表可以是任何容器类型,也可以是您手动编写的链接列表类。当我们在该列表中执行Find时,它的工作方式很慢(检查每条记录的密钥)。

答案 1 :(得分:3)

不要担心MySQL在内部做什么来快速定位记录。数据库的工作就是为你做这样的事情。只需运行SELECT [columns] FROM table WHERE [condition];查询,让数据库为您生成查询计划。请注意,您不希望使用SELECT *,因为如果您在表中添加了一列,该列将破坏依赖于特定顺序的特定列数的所有旧查询。

如果你真的想知道底层发生了什么(很高兴知道,但不自己实现它:这是数据库的目的!),你需要知道什么索引以及它们如何工作。如果表没有WHERE子句中涉及的列的索引,那么,正如您所说,数据库必须搜索表中的每一行以查找与您的条件匹配的行。但是,如果索引,数据库将搜索索引以查找所需行的确切位置,并直接跳转到它们。索引通常实现为B+-trees,这是一种搜索树,使用很少的比较来定位特定元素。在B树中搜索特定密钥非常快。 MySQL也能够使用哈希索引,但这些数据库使用的速度往往较慢。散列索引通常仅在长键(特别是字符串)上表现良好,因为它们将键的大小减小到固定的散列大小。对于整数和实数等数据类型,它们具有明确定义的排序和固定长度,B树的易于搜索通常可以提供更好的性能。

您可能希望查看关于索引的MySQL manualPostgreSQL manual中的章节。

答案 2 :(得分:1)

http://en.wikipedia.org/wiki/Hash_table

  

哈希表可以用作内存中的数据结构。也可以采用哈希表用于持久数据结构; database indices有时会使用基于哈希表的基于磁盘的数据结构,尽管balanced trees更受欢迎。

答案 3 :(得分:0)

散列表非常适合以O(1)成本查找条目,其中密钥(用于散列)已知。它们广泛用于集合库和数据库引擎中。您应该能够在互联网上找到关于它们的大量信息。为什么不从Wikipedia开始,或者只是进行Google搜索?

我不知道mysql的细节。如果在那里有一个名为“哈希表”的结构,那可能是一种使用散列来定位键的表。我相信别人会告诉你这件事。 =)

编辑:(回应评论)

确定。我将尝试做一个非常简化的解释:哈希表是一个表,其中条目基于键的功能而定位。例如,假设您要存储有关一组人的信息。如果将其存储在普通的未排序数组中,则需要按顺序迭代元素以查找要查找的条目。平均而言,这需要进行N / 2次比较。

相反,如果您根据人名的第一个字符将所有条目放在索引处。 (A = 0,B = 1,C = 2等),只要您知道名字,您就能立即找到正确的条目。这是基本的想法。您可能意识到需要一些特殊处理(重新散列或允许条目列表)才能支持具有相同首字母的多个条目。如果你有一个尺寸合适的哈希表,你应该可以直接找到你要搜索的项目。这意味着大约一次比较,以及我刚才提到的特殊处理的免责声明。

答案 4 :(得分:0)

我猜你可以使用哈希函数来获取你想要选择的ID。喜欢

SELECT * FROM table WHERE value = hash_fn(whatever_input_you_build_your_hash_value_from)

然后,您不需要知道要选择的行的ID,并且可以执行完全查询。由于您知道该行将始终具有相同的id,因为您构建了哈希值表单,并且您始终可以通过哈希函数重新创建此ID。

然而,这并不总是如此,具体取决于表的大小和最大哈希值(您的哈希值中经常有“X mod hash-table-size”)。为了解决这个问题,每次获得具有相同id的两个值时,您应该使用确定性策略。您应该检查Wikipedia以获取有关此策略的更多信息,称为冲突处理,并且应该在与哈希表相同的文章中提及。

由于提到了O(1)功能norheim.se(up),MySQL可能会在某处使用哈希表。