DBS note6:Hashing(哈希存储)

2023-11-30 20:44
文章标签 哈希 存储 note6 hashing dbs

本文主要是介绍DBS note6:Hashing(哈希存储),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

一、一般策略

二、算法简述

三、哈希缺点(Drawbacks of Hashing)

四、举例

五、外部哈希的分析


一、一般策略

由于我们无法一次性将所有数据放入内存中,我们需要构建多个不同的哈希表并将它们连接在一起。然而,这个想法存在一个问题。

如果我们构建了两个分开的哈希表,它们中都包含相同的值(例如,“Brian” 同时出现在两个表中),那么连接这两个表将导致一些 “Brian” 并非相邻。

为了解决这个问题,在将内存中的数据构建成哈希表之前,我们需要确保如果某个特定值存在于内存中,那么它的所有出现也都在内存中。换句话说,如果 “Brian” 至少在内存中出现一次,那么只有当我们的数据中的每个 “Brian” 出现都在内存中时,我们才能构建哈希表。这确保了值只能出现在一个哈希表中,使得哈希表可以安全连接。

二、算法简述

我们将使用分治算法来解决这个问题。在 “divide” 阶段,我们执行分区传递,在 “conquer” 阶段,我们构建哈希表。就像在排序笔记中一样,我们假设有 B 个可用的缓冲帧。在对数据进行哈希时,我们将使用其中 1 个缓冲区作为输入缓冲区,剩下的 B-1 个缓冲区作为输出缓冲区。

我们开始将数据从磁盘流式传输到一个输入缓冲区。有了这些输入数据后,我们希望将它们分成几个部分。每个部分都是一组页面,这些页面上的值通过特定的哈希函数都被映射到相同的哈希值。在第一轮分割中,我们会将输入缓冲区中的每条记录通过哈希函数分到 B-1 个部分中,每个部分对应 B-1 个输出缓冲区中的一个。如果某个输出缓冲区已满,相应的页面就会被写入磁盘,然后哈希过程继续。所有来自同一缓冲区的刷新页面都会在磁盘上相邻存储。第一轮分割结束时,我们在磁盘上存储了 B-1 个部分,每个部分的数据都是连续存储的。

分区的一个重要特性是,如果某个值出现在一个分区中,我们数据中所有该值的出现都会位于同一个分区。这是因为相同的值将被哈希到相同的位置。例如,如果 “Brian” 出现在一个分区中, “Brian” 将不会出现在任何其他分区中。

在第一轮分割后,我们得到了 B-1 个大小不同的分区。对于能够放入内存的分区(分区的大小小于或等于 B 页),我们可以直接进入“conquer ”阶段,开始构建哈希表。对于太大的分区,我们需要使用不同于第一轮中使用的哈希函数进行递归分区。为什么要使用不同的哈希函数呢?如果我们重复使用原始函数,每个值都将哈希到其原始分区,因此分区的大小不会减小。我们可以使用不同的哈希函数进行递归分区,直到所有分区最多有 B 页为止。

一旦所有的分区都能够放入内存,并且相同的值都出现在同一个分区中(根据分区的特性),我们就可以开始 “conquer” 阶段。首先,我们为构建最终哈希表选择一个新的哈希函数。然后,对于每个分区,我们将分区流式传输到内存中,使用新的哈希函数创建哈希表,并将生成的哈希表刷新回磁盘。

三、哈希缺点(Drawbacks of Hashing)

需要注意的是,哈希对数据倾斜非常敏感。数据倾斜发生在我们进行哈希的值不符合均匀分布的情况下。由于哈希分区的特性(相同值的所有哈希最终都会在同一个分区中),数据倾斜可能导致分区大小非常不均匀,这对我们的目的来说是不理想的。此外,并非所有的哈希函数都是相同的。在最理想的情况下,我们的哈希函数是一个均匀的哈希函数,将数据分成“均匀”的大小相等的分区。然而,哈希函数通常是非均匀的,会在所有分区之间不均匀地分布数据。在本课程中,除非另有说明,我们将使用均匀哈希函数。在下面的两个图像中,圆柱体表示在磁盘上发生的步骤,正方形表示在内存中发生的步骤,两者之间的线表示数据在磁盘和内存之间的流动。

下面的图像展示了哈希的两个阶段 - divide 和 conquer - 当不需要递归分区时。这意味着在初始分区后,所有分区都适合于 B 页内。请注意,在 “divide ” 阶段中,1 个缓冲页专用于输入缓冲区,其余的 B-1 个用于分区。然后,在 “conquer ” 阶段中,对每个单独的分区使用不同的哈希函数 h_r 来形成内存中的哈希表。

下面的图像显示了递归分区。请注意,附加的阶段仅适用于大小大于 B 页的分区(灰色分区)。

四、举例

在以下示例中,我们假设我们有 B=3 个缓冲页可用。我们还假设对于第一个哈希函数,Brian 和 Eric 哈希到相同的值,但对于第二个哈希函数,它们哈希到不同的值,而 Jamie 和 Lakshya 对于第一个哈希函数哈希到相同的值。

在第一次分区传递(分区传递 1)后,分区 0 有 4 页,分区 1 有 2 页。分区 1 可以放入内存,但分区 0 不能。这意味着我们必须对分区 0 进行递归分区。

经过第二次分区传递后,分区 0 被分为两部分:分区 0.a 有 2 页,分区 0.b 有 2 页。由于分区 1 已经适应内存,所以在第二次分区传递期间它没有被分区。

一旦所有分区(0.a、0.b、1)适应内存,我们执行 "conquer" 并构建哈希表。可以看到在最终的 "conquer" 后,所有相同值都在一起,这是我们的最终目标。

五、外部哈希的分析

我们无法像排序算法中那样简单地创建一个计算I/O数量的公式,因为我们不知道分区的大小。我们首先需要认识到的一件事是,在分区后表的页数可能会增加。为了理解这一点,考虑下面的表,我们可以在一页上容纳两个整数:

[1, 2] [1, 4] [3, 4]

假设B=3,因此我们只将数据分为2个分区。假设1和3散列到分区1,2和4散列到分区2。分区后,分区1将包含:

[1, 1],[3]

而分区2将包含:

[4, 2],[4]

请注意,我们现在有4页,而我们一开始只有3页。因此,计算 I/O 数量的唯一可靠方法是查看每个阶段,看看将读取什么和将写入什么。设 m 为所需的总分区次数,r_i为第 i 个分区阶段需要读取的页数,w_i 为第 i 个分区阶段需要写出的页数,X 为分区后我们需要构建哈希表的总页数。以下是 I/O 数量的公式:

$(\sum_{i=1}^{m}r_i+w_i)+2X$

这个求和并没有告诉我们任何我们之前不知道的东西;我们需要逐个阶段地查看并弄清楚究竟读取了什么和写入了什么。最后的2X部分表示,为了构建我们的哈希表,我们需要读取和写入分区后拥有的每一页。

以下是一些重要的性质:

  1. r_0 = N
  2. r_i \leq w_i
  3. w_i \geq r_i+1
  4. X \geq N

性质 1 表示我们在第一次分区时必须读取每一页。这直接来自算法。

性质 2 表示在分区期间,我们将写出至少与读入的页数相同的页面。这直接来自上面的解释 - 我们可能在分区 partitioning pass 期间创建额外的页面。

性质 3 表示我们在分区通行期间读入的页面数不会超过之前写出的页面数。在最坏的情况下,第 i 次通行的每个分区都需要重新分区,因此这将要求我们读入每一页。然而,在大多数情况下,某些分区将足够小以适应内存,因此我们可以读入比上一次通行期间产生的页面更少的页面。

性质 4 表示我们用于构建哈希表的页面数至少与我们开始时的数据页面数一样多。这源于分区pass期间只能增加数据页数,而不能减少。

以上,DBS note6:Hashing(哈希存储)

祝好。

这篇关于DBS note6:Hashing(哈希存储)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/438476

相关文章

哈希leetcode-1

目录 1前言 2.例题  2.1两数之和 2.2判断是否互为字符重排 2.3存在重复元素1 2.4存在重复元素2 2.5字母异位词分组 1前言 哈希表主要是适合于快速查找某个元素(O(1)) 当我们要频繁的查找某个元素,第一哈希表O(1),第二,二分O(log n) 一般可以分为语言自带的容器哈希和用数组模拟的简易哈希。 最简单的比如数组模拟字符存储,只要开26个c

异构存储(冷热数据分离)

异构存储主要解决不同的数据,存储在不同类型的硬盘中,达到最佳性能的问题。 异构存储Shell操作 (1)查看当前有哪些存储策略可以用 [lytfly@hadoop102 hadoop-3.1.4]$ hdfs storagepolicies -listPolicies (2)为指定路径(数据存储目录)设置指定的存储策略 hdfs storagepolicies -setStoragePo

HDFS—存储优化(纠删码)

纠删码原理 HDFS 默认情况下,一个文件有3个副本,这样提高了数据的可靠性,但也带来了2倍的冗余开销。 Hadoop3.x 引入了纠删码,采用计算的方式,可以节省约50%左右的存储空间。 此种方式节约了空间,但是会增加 cpu 的计算。 纠删码策略是给具体一个路径设置。所有往此路径下存储的文件,都会执行此策略。 默认只开启对 RS-6-3-1024k

usaco 1.3 Prime Cryptarithm(简单哈希表暴搜剪枝)

思路: 1. 用一个 hash[ ] 数组存放输入的数字,令 hash[ tmp ]=1 。 2. 一个自定义函数 check( ) ,检查各位是否为输入的数字。 3. 暴搜。第一行数从 100到999,第二行数从 10到99。 4. 剪枝。 代码: /*ID: who jayLANG: C++TASK: crypt1*/#include<stdio.h>bool h

哈希表的底层实现(1)---C++版

目录 哈希表的基本原理 哈希表的优点 哈希表的缺点 应用场景 闭散列法 开散列法 开放定值法Open Addressing——线性探测的模拟实现 超大重点部分评析 链地址法Separate Chaining——哈希桶的模拟实现 哈希表(Hash Table)是一种数据结构,它通过将键(Key)映射到值(Value)的方式来实现快速的数据存储与查找。哈希表的核心概念是哈希

速了解MySQL 数据库不同存储引擎

快速了解MySQL 数据库不同存储引擎 MySQL 提供了多种存储引擎,每种存储引擎都有其特定的特性和适用场景。了解这些存储引擎的特性,有助于在设计数据库时做出合理的选择。以下是 MySQL 中几种常用存储引擎的详细介绍。 1. InnoDB 特点: 事务支持:InnoDB 是一个支持 ACID(原子性、一致性、隔离性、持久性)事务的存储引擎。行级锁:使用行级锁来提高并发性,减少锁竞争

哈希表的封装和位图

文章目录 2 封装2.1 基础框架2.2 迭代器(1)2.3 迭代器(2) 3. 位图3.1 问题引入3.2 左移和右移?3.3 位图的实现3.4 位图的题目3.5 位图的应用 2 封装 2.1 基础框架 文章 有了前面map和set封装的经验,容易写出下面的代码 // UnorderedSet.h#pragma once#include "HashTable.h"

【408数据结构】散列 (哈希)知识点集合复习考点题目

苏泽  “弃工从研”的路上很孤独,于是我记下了些许笔记相伴,希望能够帮助到大家    知识点 1. 散列查找 散列查找是一种高效的查找方法,它通过散列函数将关键字映射到数组的一个位置,从而实现快速查找。这种方法的时间复杂度平均为(

PHP: 深入了解一致性哈希

前言 随着memcache、redis以及其它一些内存K/V数据库的流行,一致性哈希也越来越被开发者所了解。因为这些内存K/V数据库大多不提供分布式支持(本文以redis为例),所以如果要提供多台redis server来提供服务的话,就需要解决如何将数据分散到redis server,并且在增减redis server时如何最大化的不令数据重新分布,这将是本文讨论的范畴。 取模算法 取模运

哈希表题总结

哈希表题总结 hot100两数之和字母异位词分组最长连续序列 hot100 两数之和 题目链接: 1.两数之和 代码: class Solution {public int[] twoSum(int[] nums, int target) {Map<Integer,Integer> map = new HashMap<>();int n = nums.length;for