当前位置: 首页 > 知识库问答 >
问题:

为什么SparkSQL认为索引的支持不重要?

嵇弘新
2023-03-14

引用Spark数据框架、数据集和SQL手册:

Spark中还没有包括一些配置单元优化。由于Spark SQL的内存计算模型,其中一些(如索引)不那么重要。其他版本将在Spark SQL的未来版本中发布。

作为Spark的新手,我对此有点困惑,原因有两个:

>

即使假设数据适合内存,对非常大的数据集进行完整扫描也可能需要很长时间。我读了这篇反对在内存数据库中建立索引的文章,但我并不信服。这里的示例讨论了对10000000条记录表的扫描,但这并不是真正的大数据。扫描一个包含数十亿条记录的表可能会导致简单的“SELECT x WHERE y=z”类型的查询花费很长时间,而不是立即返回

我知道索引有一些缺点,比如插入/更新速度较慢、空间需求等。但在我的用例中,我首先处理大量数据,并将其加载到Spark SQL中,然后将这些数据作为一个整体进行研究,无需进一步修改。Spark SQL对于数据的初始分布式处理和加载非常有用,但由于缺少索引,交互式探索比我预期的要慢,也更麻烦。

我想知道为什么星火SQL团队认为索引不重要到偏离他们的路线图的程度。是否有不同的使用模式可以提供索引的好处,而无需独立实现等效的东西?

共有2个答案

陶俊晤
2023-03-14

一般来说,索引的效用充其量是有问题的。相反,数据划分更重要。它们是非常不同的东西,仅仅因为您选择的数据库支持索引并不意味着考虑到Spark试图做的事情,它们是有意义的。而且和“在记忆里”无关。

那么,什么是索引呢?

在永久存储极其昂贵(而不是基本免费)的年代,关系数据库系统都是为了最大限度地减少永久存储的使用。关系模型需要将一条记录拆分为多个部分——对数据进行规范化——并将它们存储在不同的位置。要读取客户记录,可能需要读取客户表、客户类型表,从地址表中取出几个条目,等等。如果您有一个解决方案,需要读取整个表才能找到您想要的内容,这是非常昂贵的,因为您必须扫描这么多表。

但这并不是做事的唯一方式。如果不需要固定宽度的列,可以将整个数据集存储在一个位置。与其在一堆表上进行完整的表扫描,不如只在单个表上进行。这并不像你想象的那么糟糕,尤其是如果你可以对数据进行分区的话。

40年后,物理定律发生了变化。硬盘驱动器的随机读/写速度和线性读/写速度有很大差异。基本上,每个磁盘每秒可以移动350个头部。(或多或少,但这是一个很好的平均数字。)另一方面,单个磁盘驱动器每秒可以读取大约100 MB的数据。这是什么意思?

计算一下并思考一下——这意味着如果每次磁盘磁头移动读取的数据少于300KB,您就会限制驱动器的吞吐量。

认真地。想一想。

索引的目标是允许您将磁盘头移动到磁盘上所需的精确位置,然后读取该记录——比方说作为客户记录的一部分加入的地址记录。我说,那没用。

如果我设计一个基于现代物理学的索引,它只需要让我在目标数据的100KB左右(假设我的数据已经大块地排列出来——但我们在这里谈论的是理论)。根据上面的数字,任何比这更精确的都只是浪费。

现在回到标准化的表格设计。假设一个customer记录实际上被分成了5个表中的6行。总共6个磁头移动(我假设索引缓存在内存中,所以没有磁盘移动)。这意味着我可以读取1.8MB的线性/非标准化客户记录,并且同样高效。

客户历史呢?假设我不只是想看到客户今天的样子——想象一下我想要完整的历史记录,或者历史记录的一个子集?把上面的数字乘以10或20,你就得到了图片。

比索引更好的是数据划分——确保所有客户记录最终都在一个分区中。这样,只需移动一个磁盘头,我就可以读取整个客户历史。一个磁盘磁头移动。

再告诉我一次你为什么要索引。

指数vs___?

不要误解我——“预先烹饪”你的搜索是有价值的。但是物理定律提出了比传统索引更好的方法。与其将客户记录存储在一个位置,并创建一个指向它的指针——索引——为什么不将记录存储在多个位置呢?

请记住,磁盘空间基本上是免费的。与其尽量减少我们使用的存储量(这是关系模型的过时产物),不如将磁盘用作搜索缓存。

如果您认为有人希望看到按地理位置和销售代表列出的客户,请将您的客户记录以优化搜索的方式存储多份副本。就像我说的,像内存缓存一样使用磁盘。构建持久数据以镜像内存缓存,而不是通过绘制不同的持久数据片段来构建内存缓存,这样你所要做的就是读取它。事实上,你甚至不用费心把它存储在内存中——只要在每次需要的时候直接从磁盘上读取就行了。

如果你认为这听起来很疯狂,考虑一下——如果你把它缓存在内存中,你可能会缓存两次。很可能你的操作系统/驱动器控制器使用主存作为缓存。不要费心缓存数据,因为其他人已经缓存了!

但我离题了。。。

长话短说,Spark绝对支持正确的索引——从原始数据创建复杂派生数据的能力,以使未来的使用更加高效。它只是没有按你想要的方式做。

姬朗
2023-03-14

索引输入数据

  • 外部数据源索引不在Spark范围内的根本原因是Spark不是一个数据管理系统,而是一个批处理数据处理引擎。因为它不拥有它正在使用的数据,所以它无法可靠地监控变化,因此无法维护索引。
  • 如果数据源支持索引,Spark可以通过谓词向下推等机制间接利用它。

索引分布式数据结构:

  • 标准索引技术需要持久且定义良好的数据分布,但Spark中的数据通常是短暂的,其精确分布是不确定的
  • 通过适当的分区结合柱状存储和压缩实现的高级数据布局可以提供非常高效的分布式访问,而无需创建、存储和维护索引的开销。这是内存中不同的列式系统使用的常见模式

尽管如此,星火生态系统中确实存在一些形式的索引结构。最值得注意的是数据库在其平台上提供数据跳过索引。

其他项目,如Succent(目前大多处于非活动状态)采用不同的方法,并使用支持随机访问的高级压缩技术。

当然,这引发了一个问题——如果你需要有效的随机访问,为什么不使用一个从一开始就被设计为数据库的系统呢。这里有很多选择,其中至少有几个是由Apache基金会维护的。同时,随着项目的发展,Spark也在发展,您使用的报价可能无法完全反映Spark未来的发展方向。

 类似资料:
  • 本文向大家介绍为什么Java不支持<<相关面试题,主要包含被问及为什么Java不支持<<时的应答技巧和注意事项,需要的朋友参考一下 Java添加了运算符“ >>>”来执行逻辑右移,但是由于 逻辑和算术左移运算是相同的 ,因此Java中没有“ <<<”运算符。 来自Java的Shifts …

  • 我注意到一件奇怪的事情,显然Firefox说它支持HTTPS上的Brotli,但不支持HTTP?Brotli与gzip类似,但效率更高,为什么它会将其限制为HTTPS?在HTTPS选项卡上,我看到: 他被派去了。但在另一个网站上,我没有看到。为什么它不能做Brotli压缩HTTP?

  • 问题内容: Java为什么不包括对无符号整数的支持? 在我看来,这是一个奇怪的遗漏,因为它们允许人们编写不太可能在意外大的输入上产生溢出的代码。 此外,使用无符号整数可以是一种自我证明的形式,因为它们指示无符号int打算保留的值永远不会为负。 最后,在某些情况下,无符号整数对于某些操作(例如除法)可能更有效。 包括这些的不利之处是什么? 问题答案: 在两行之间阅读时,我认为逻辑是这样的: 通常,J

  • 我不能在设置cookie后返回任何地方,cookie设置正确,但在设置cookie后,它不会重定向任何地方。 下面是我的代码: 下面是JavaScript的功能: 这是我的函数,但不重定向到索引或其他任何地方:

  • 本文向大家介绍为什么jsonp不支持post的方法?相关面试题,主要包含被问及为什么jsonp不支持post的方法?时的应答技巧和注意事项,需要的朋友参考一下 jsonp是跨域解决方案的其中一种方式,依赖script来突破同源策略的限制,而script是通过get方式拉取资源的。 可参考我的文章中的jsonp的实现

  • 我有一个带有tabbarcontroller的应用程序,两个带有它的controller,现在在一个controller中我以肖像模型显示了uiactionsheet: UIActionSheet*ActionSheet=[[UIActionSheet alloc]InitWithTitle:@""Delegate:nil CancelButtonTitle:@"Cancel"Destructiv