技术架构定位
数据局部性优化是大数据处理系统中提升性能的关键策略,它基于"移动计算而非移动数据"的核心理念,在分布式计算环境中占据着战略性地位。这种优化模式通过减少数据传输量,显著提升系统吞吐量并降低延迟。
在分布式环境中,数据与计算的关系就像是两个舞伴,他们的距离决定了舞蹈的流畅程度。数据局部性优化就是精心编排这场"舞蹈",确保数据与需要处理它的计算资源保持最近的距离,从而减少"舞伴"之间的奔波时间。这一优化策略在大数据处理中的地位尤为重要,因为随着数据规模的爆炸性增长,数据移动的成本已经成为系统性能的主要瓶颈。
当今的分布式计算框架如Spark、Hadoop和Flink都将数据局部性作为核心设计原则,通过各种机制尽量在数据所在位置执行计算任务。这种优化不仅提高了系统的吞吐量和响应速度,还减轻了网络负担,降低了能源消耗,可谓一举多得。本文将深入探讨数据局部性优化的核心策略、实现技术及其在现代大数据系统中的应用实践。
计算下推策略
计算下推(Compute Pushdown)是数据局部性优化的核心策略之一,它颠覆了传统的"先获取数据再计算"的范式,转而采用"将计算送往数据所在地"的思路。这种策略就像是派遣特工前往情报所在地执行任务,而不是将所有情报运回总部再处理,大大提高了任务执行效率。
谓词下推原理
谓词下推(Predicate Pushdown)是计算下推的典型代表,通过将过滤条件(谓词)尽早应用到数据源,减少需要传输和处理的数据量。这种技术就像是在购物前先看好商品清单,避免在商场里漫无目的地逛,节省了大量时间和精力。
在具体实现中,谓词下推可以采取多种形式:SQL引擎将WHERE子句中的过滤条件下推到表扫描层;分布式查询处理器将过滤条件下推到数据节点;流处理系统将过滤条件下推到数据源或事件产生者。无论形式如何,核心思想都是"在数据发源地进行筛选",减少后续环节的数据量。
谓词下推的效果通常十分显著。在一个典型的数据仓库查询中,通过将过滤条件下推到存储层,可能将需要处理的数据量从TB级降到GB级,或从GB级降到MB级,相应地减少了网络传输、内存消耗和CPU计算时间。这种千倍万倍的数据量减少,直接转化为查询性能的倍数级提升。
现代数据系统已经发展出越来越智能的下推机制。例如,Spark SQL的Catalyst优化器能够自动识别可下推的过滤条件,并根据数据源的能力决定下推策略;Presto可以将复杂查询中的部分计算下推到各种异构数据源;而Flink则支持将窗口聚合等复杂操作部分下推到数据源进行预处理。这些技术大大扩展了计算下推的应用场景和效果。
投影下推技术
与谓词下推类似,投影下推(Projection Pushdown)专注于减少不必要的列数据传输。它就像是提前告诉图书管理员只需要检索书的标题和作者,而不需要全部内容,从而减少了搬运的工作量。
在大数据环境中,表可能有数百甚至上千列,而典型查询可能只涉及其中的几列。通过将投影操作(SELECT列表)下推到存储层,系统可以仅读取和传输查询真正需要的列数据,显著减少I/O和网络负载。对于宽表查询优化,这种技术的效果尤为明显,在某些案例中可将数据传输量减少90%以上。
Parquet和ORC等列式存储格式天然支持投影下推,它们可以只读取查询所需的列文件,跳过其他列。这种物理存储特性与逻辑优化相结合,形成了强大的列裁剪(Column Pruning)能力,成为OLAP系统性能优化的标准技术。
聚合下推实践
聚合下推(Aggregation Pushdown)更进一步,将统计聚合操作(如COUNT、SUM、AVG等)尽可能地推送到数据所在位置执行。这种技术类似于让各地分支机构先汇总本地报表,再向总部提交摘要,而不是将所有原始数据传送到总部再计算,大大减轻了总部的负担。
聚合下推的关键优势在于可以显著减少数据传输量。例如,对于一个计算用户平均年龄的查询,通过聚合下推,每个数据节点只需要返回本地用户的总数和年龄总和,而不是所有用户的详细记录。这种本地预聚合可以将网络传输从原始数据量级降低到聚合结果量级,减少量通常是几个数量级。
在实际系统中,聚合下推的实现需要考虑聚合函数的特性。一些聚合函数(如SUM、COUNT)可以直接分阶段计算,而其他函数(如MEDIAN)则需要特殊处理。现代大数据系统通常采用代数聚合(Algebraic Aggregation)框架,将复杂聚合分解为可分布式执行的子步骤,在保持正确性的同时最大化局部计算的优势。
MapReduce模型是聚合下推的经典应用,它通过Map阶段的本地聚合(Combiner)显著减少Shuffle阶段的数据量。Spark在此基础上进一步优化,支持更复杂的多级聚合策略,能够根据数据分布特性动态调整聚合下推的粒度和策略。
数据缓存层设计
合理设计数据缓存层是实现局部性优化的核心手段之一,它通过在计算节点附近保存频繁访问的数据副本,减少远程数据获取的需求。这种设计就像城市的多级商业体系,从大型购物中心到社区便利店,根据访问频率和紧急程度提供不同层次的服务。
多级缓存架构
多级缓存架构(Multi-level Cache Architecture)是现代大数据系统优化局部性的标准方法,它模仿了计算机硬件中的内存层次结构,构建了从远程存储到本地内存的多层数据缓存体系。
这种层次化缓存设计的关键在于识别和利用数据访问的"局部性原理":时间局部性(最近访问过的数据可能很快再次被访问)和空间局部性(访问某数据后,其附近的数据也可能被访问)。通过将频繁访问的数据保存在更快的存储层,系统可以显著减少平均数据访问时间。
在实际大数据系统中,多级缓存通常包括这几个层次:
计算节点内存缓存是最快的数据访问层,通常由框架直接管理。如Spark的内存存储区,它可以配置为纯内存存储或内存与磁盘混合存储;为了提高GC效率,其还进一步区分了堆内存和堆外内存两种方式。这一层缓存的特点是速度极快(微秒级访问),但容量受限(通常为GB级)。
计算节点本地磁盘缓存提供了第二层数据访问速度。Spark的BlockManager和Flink的TaskManager都支持将计算中间结果或频繁访问的数据溢写到本地磁盘。相比远程数据访问,本地磁盘读取可以提供10-100倍的速度提升,尤其是在使用SSD的系统中。这一层的特点是中等速度(毫秒级)和中等容量(TB级)。
集群级共享缓存层通常由专门的缓存系统提供,如Alluxio(原Tachyon)、Redis集群或内存数据网格。这类系统通过将热点数据分布在集群内存中,既提供了比远程存储快10倍以上的访问速度,又能支持PB级的大容量缓存。其关键特性是数据自动在集群节点间复制和平衡,应用无需关心数据的具体物理位置。
最后一层是远程持久存储,如HDFS、S3或其他云存储系统。这层提供了持久化保证和几乎无限的容量,但访问速度最慢(通常是秒级)。在数据局部性优化中,这一层通常作为数据的权威来源,而上层缓存则负责优化访问性能。
多级缓存架构的高效运行依赖于精心设计的缓存策略,包括回收策略(如LRU、LFU或CLOCK)、缓存一致性协议、数据预取机制等。现代大数据框架不断完善这些策略,使缓存系统能够适应各种工作负载特性,最大化数据局部性带来的性能收益。
预取与异步加载
数据预取(Prefetching)和异步加载(Asynchronous Loading)技术进一步优化了缓存系统,通过预测和提前加载可能需要的数据,减少等待时间。这就像餐厅在高峰期提前准备半成品,顾客下单后可以更快地上菜。
顺序预取(Sequential Prefetching)是最常见的预取策略,基于数据访问的空间局部性原理。当系统检测到对某区域数据的顺序读取模式时,会自动预取后续数据块。这种策略在大规模顺序扫描场景下尤其有效,可以将I/O等待时间缩短80%以上。如HDFS的预读机制会根据历史读取模式动态调整预读窗口大小,在保证命中率的同时避免过度预取。
智能预取(Intelligent Prefetching)则采用更复杂的预测模型,如基于访问历史的模式识别或机器学习算法,实现更精准的数据预测。例如,Alluxio可以分析作业历史记录,识别出频繁一起访问的数据块集合,并据此制定预取策略。这种预取可能不限于简单的顺序模式,而能识别复杂的数据访问关系,如表连接操作中的相关列数据。
异步加载则解决了"预取失败"情况下的性能问题。通过将数据加载操作与计算处理解耦,系统可以在后台持续加载数据,而前台计算线程则处理已就绪的数据。这种设计显著减少了因数据加载造成的计算资源闲置,提高了整体资源利用率。
在实现上,异步加载通常采用生产者-消费者模式,用专门的线程池负责数据获取,计算线程则从预加载缓冲区消费数据。例如,Spark的UnifiedMemoryManager实现了动态平衡存储和执行内存,可以根据运行时负载特性灵活调整预取侵略性;而Flink的网络栈则优化了远程数据传输,使计算算子可以在接收完整数据前开始处理部分记录。
预取和异步加载技术的关键挑战在于平衡预测准确性与资源开销。过度预取可能浪费带宽和缓存空间,甚至挤占有用数据;而预取不足则无法充分发挥其性能优势。因此,现代系统通常采用自适应策略,根据实际工作负载动态调整预取行为。
缓存一致性保障
在分布式环境中,缓存的使用不可避免地引入了数据一致性问题。高效的缓存一致性机制需要在性能和正确性之间取得平衡,确保系统既能从缓存中获得性能提升,又不会因数据不一致而产生错误结果。
缓存一致性模型定义了系统对数据更新的可见性保证。大数据系统常用的模型包括:强一致性(任何更新立即对所有后续读取可见)、最终一致性(更新最终会传播到所有缓存,但有延迟)和会话一致性(在单个会话或事务内保证一致,跨会话则提供较弱保证)。选择何种模型需要根据应用需求和性能目标权衡。
更新传播机制决定了数据变更如何从源存储同步到各级缓存。常见策略包括:
写穿透(Write-Through)将更新同时写入缓存和底层存储,保证强一致性但增加写延迟。 写回(Write-Back)先写入缓存,再异步写回存储,提高写性能但牺牲部分一致性。 写无效(Write-Invalidate)在数据更新时废除所有缓存副本,强制后续读取从最新源获取,简化一致性维护但可能导致"缓存颠簸"。
具体实现上,现代大数据系统采用多种技术确保缓存一致性。版本化缓存使用版本号或时间戳标记数据项,允许系统检测和解决冲突。HDFS的namenode和datanode之间通过块版本号维护元数据一致性,避免读取过时数据块。
租约机制(Lease)为缓存内容提供了有时间限制的"所有权",减少协调开销。持有租约的节点可以在租约期内自由访问和修改缓存数据,无需频繁与中央协调者通信。GFS和HDFS都使用租约机制管理块修改权限,在保证正确性的同时提高并发写入性能。
在缓存预热和替换方面,系统需要智能决策哪些数据应被缓存、何时清除缓存。大数据处理中,工作集大小(Working Set Size)往往远超单机内存容量,因此高效的缓存替换算法至关重要。SparkSQL优先缓存小表和广播变量;HBase采用分层缓存设计,将不同访问模式的数据分配到不同级别缓存。
最终,缓存一致性方案的选择需要考虑应用特性。分析型查询倾向于采用较弱一致性模型换取性能;而事务处理系统则可能需要强一致性保证。优秀的系统设计会提供灵活的一致性选项,允许用户根据场景做出合适选择。
数据分布感知调度
数据分布感知调度(Data-aware Scheduling)是大数据系统实现计算与数据协同的关键机制,它通过将计算任务调度到数据所在位置,最大化数据局部性收益。这种方法就像是在城市规划中将商业中心建在人口密集区,减少人们的通勤距离,提高整体效率。
任务与数据协同
在分布式系统中,任务调度器是实现计算与数据协同的指挥中心。一个感知数据分布的调度器需要掌握两方面关键信息:任务的数据依赖(哪些数据块将被访问)和数据的物理分布(这些数据块位于哪些节点)。通过匹配这两组信息,调度器可以做出最优的任务分配决策。
数据本地性优先级是现代调度器的核心概念,它定义了多层次的本地性目标,从最优到次优:节点本地性(Node Locality)表示任务与数据在同一物理节点,提供最佳性能;机架本地性(Rack Locality)表示任务与数据在同一网络机架但不同节点,提供次优性能;数据中心本地性表示任务与数据在同一数据中心;最后是任意位置(Any Locality),即接受任务在任何可用节点执行,通常作为最后选择。
调度系统会根据当前系统负载和资源可用性,在这些本地性级别之间做出权衡。例如,Hadoop MapReduce的调度器默认会在等待节点本地性超过一定时间后(可配置),转为接受机架本地性任务;如果还不能满足,最终会分配到任意可用节点。这种妥协机制确保系统在追求数据局部性的同时不会因过度等待而造成资源浪费。
在具体实现上,不同的调度器采用不同策略平衡数据局部性与其他调度目标。Hadoop的Capacity Scheduler和Fair Scheduler都支持延迟调度(Delay Scheduling),允许任务短暂等待以获得更好的数据局部性;YARN添加了基于心跳的资源请求机制,使计算框架可以表达特定的数据局部性需求;而Spark则在DAG调度层分析任务的数据依赖,生成具有位置偏好的任务集。
现代系统还考虑了更复杂的调度因素,如数据倾斜、负载均衡和故障恢复。智能调度器不仅考虑静态的数据分布,还分析动态的系统状态,如节点负载、网络拓扑和历史执行统计,做出更全面的调度决策。例如,Spark在检测到某节点执行慢任务时会主动启动投机任务(Speculative Tasks)在其他节点上执行,即使这意味着放弃部分数据局部性优势。
在实际生产环境中,数据局部性只是众多调度考量之一。系统通常需要在数据局部性、公平性、优先级、截止时间和资源利用率等多个目标间平衡。因此,现代调度框架提供了丰富的配置选项,允许用户根据具体工作负载特性调整各种权重和阈值,找到最适合其应用场景的平衡点。
数据再平衡策略
在长期运行的分布式系统中,初始的数据分布往往会因各种因素而变得不均衡,影响局部性优化效果。数据再平衡(Data Rebalancing)策略通过动态调整数据分布,恢复系统平衡并优化局部性。这就像城市交通管理,通过分流和引导,缓解交通拥堵,使人员和物资流动更加顺畅。
数据分布不均衡的来源多种多样:新节点加入集群后数据分布偏向旧节点;热点数据访问导致部分节点负载过高;节点故障导致数据重新分布不均;或者是应用访问模式随时间变化,原本的分布不再最优。无论原因如何,不均衡的数据分布都会导致资源利用率降低,网络传输增加,整体性能下降。
再平衡过程需要谨慎设计,以最小化对在线服务的影响。通常采用以下原则:增量执行,每次只移动少量数据,避免大规模迁移造成服务中断;后台运行,使用闲置资源进行数据传输,优先保证前台服务质量;智能选择,基于成本模型选择迁移收益最大的数据块。
HDFS的均衡器(Balancer)是典型的再平衡工具,它分析数据节点的使用率分布,识别过载和轻载节点,然后制定块迁移计划,将数据从高利用率节点移至低利用率节点。用户可以设置阈值控制平衡程度,以及带宽限制避免迁移影响正常服务。
HBase和Cassandra等分布式数据库系统具有更复杂的再平衡机制,它们不仅考虑数据大小均衡,还考虑请求负载均衡。这些系统可以识别热点区域并自动分裂(Split)或合并(Merge)数据分区,将热点数据分散到多个节点处理,同时支持范围分区和哈希分区等多种策略,适应不同的访问模式。
在云环境中,数据再平衡变得更加动态和复杂。系统需要适应弹性伸缩的资源池,节点可能随时加入或离开集群。Amazon S3的智能分层存储(Intelligent-Tiering)和Google Cloud Storage的自动迁移(Auto Class)都能根据访问模式自动将数据在不同存储级别间迁移,优化成本和性能。
最先进的系统正在探索基于机器学习的自适应再平衡。这类系统监控应用访问模式,预测未来的数据需求热点,并据此主动调整数据分布。例如,阿里巴巴的X-Engine存储引擎使用学习模型预测数据访问频率,提前将热数据移至性能更高的存储层,将冷数据迁至成本更低的存储层,实现访问模式变化前的主动适应。
数据聚类优化
数据聚类优化(Data Clustering Optimization)通过调整数据的物理组织方式,使相关数据在存储介质上物理上邻近,从而提高访问效率。这种优化就像图书馆将同一主题的书籍放在相邻书架,使读者能够在一个区域找到所有相关资料,减少来回走动的时间。
相关数据物理邻近存储
相关数据的物理邻近存储是大数据系统提高读取效率的重要策略。通过识别并组织常一起访问的数据项,系统可以减少磁盘寻道次数和网络请求数量,显著提升处理性能。
列族存储(Columnar Storage)是数据聚类的典型应用,它将表格数据按列而非按行组织,使同一列的值物理相邻。这种设计特别适合分析查询,这类查询通常只访问表中少数几列。Apache Parquet、ORC和Kudu等列存格式进一步扩展了这一概念,增加了行组(Row Group)和列块(Column Chunk)等概念,优化了不同访问模式下的性能。
为了更精细地控制数据布局,许多系统引入了数据分区(Data Partitioning)机制。与简单分片不同,数据分区基于数据内容(如时间范围、地理位置或业务类别)而非机械位置划分数据。例如,在Hive中可以按日期分区表数据,使查询特定日期范围的数据时只需扫描相关分区,显著减少I/O量。最新的Iceberg和Delta Lake表格式进一步引入了精细的分区演进和分区裁剪能力,使分区方案可以随业务需求变化而调整。
局部敏感哈希(Locality-Sensitive Hashing, LSH)是一种更高级的数据组织方法,它确保相似数据具有相似的散列值,从而被物理地存储在相近位置。这种技术特别适用于空间数据、图像检索和相似性搜索等应用。例如,Elasticsearch的地理空间索引使用基于Z曲线的编码,将二维空间中相近的点映射到一维索引上的相近位置,加速地理范围查询。
现代数据湖系统采用了更智能的数据组织策略,如根据查询历史自动优化数据布局。Databricks的Delta Lake可以根据数据访问模式执行自动优化操作(Auto Optimize),如小文件合并(Compaction)和Z-Ordering,后者是一种多维聚类技术,能够同时优化多个列的数据局部性。类似地,Snowflake的自动聚类(Auto-clustering)功能持续监控查询模式,并在后台重新组织数据,使最常一起查询的数据保持物理邻近。
分区修剪技术
分区修剪(Partition Pruning)技术通过智能地排除与查询条件无关的数据分区,大幅减少需要处理的数据量。这就像是快递公司使用邮政编码系统,可以直接将包裹送到正确的区域,而不需要在整个城市搜索收件人。
分区键选择是分区修剪的基础。理想的分区键应该是查询条件中经常出现的字段,且数据分布相对均匀。常见的分区键包括:日期/时间字段,用于按天/周/月分区;地理位置信息,适用于地理空间分析;业务类别,如产品类型、用户组或事件类型;哈希值,用于均衡分区但保留某种聚类特性。
多级分区(Multi-level Partitioning)进一步提高了修剪效率。例如,Hive支持对表进行多级分区,如先按年分区,再按月分区,最后按日分区。这种层次结构使系统可以在不同粒度上进行修剪,如查询特定月份数据时只需扫描该月的分区,而不是整年数据。
动态分区(Dynamic Partitioning)解决了预分区的局限。传统的静态分区要求预先知道所有分区值,而动态分区允许系统根据数据内容自动创建新分区。Hive、Spark和Flink等系统都支持动态分区,使数据加载过程更加灵活高效。
在实际应用中,分区修剪的效果取决于查询与分区方案的匹配度。若查询条件直接使用分区键,如"WHERE year=2023 AND month=4",系统可以直接定位到相关分区;但若查询使用分区键的转换形式,如"WHERE date_column > ‘2023-04-01’",则需要查询优化器进行额外分析才能应用修剪。现代查询引擎如SparkSQL、Presto和Impala都实现了复杂的分区修剪逻辑,能够处理各种谓词表达式。
统计信息辅助的修剪进一步扩展了这一技术。通过维护每个分区的统计信息(如最小值、最大值、空值比例等),系统可以在查询时进行更精确的修剪。例如,若查询条件为"WHERE salary > 100000",且某分区的salary最大值为90000,则该分区可以被安全跳过,即使salary不是分区键。
最新的表格式如Apache Iceberg和Delta Lake提供了更强大的修剪能力,它们维护详细的文件级元数据,支持多维过滤和嵌套数据的修剪。Iceberg的"隐藏分区"(Hidden Partitioning)特别创新,它将分区方案从物理存储中抽象出来,使分区策略可以随时调整而无需重写数据。
分区与技术关联
数据局部性优化与大数据生态系统中的多种技术和模式密切相关,它既借鉴了经典计算机科学原理,又适应了现代分布式计算的特点,形成了独特的技术体系。
数据局部性优化与分区与分片策略有着天然的联系。分区策略决定了数据如何在集群中分布,直接影响数据局部性的实现基础。例如,合理的哈希分区可以使相关记录集中在相同或邻近节点,为局部性优化创造条件;而键范围分区则有利于区间扫描的局部性。Kafka使用基于主题和分区的路由机制确保消息的本地性;HBase通过region的设计实现数据按键范围的聚类存储。这些分区机制都为上层应用提供了利用数据局部性的可能。
分布式存储原理为数据局部性提供了理论基础。GFS(Google File System)的大块设计(Chunk Design)和数据本地化调度成为后来许多系统的蓝图;HDFS的副本放置策略(机架感知复制)权衡了数据可靠性和访问局部性;S3和Azure Blob等对象存储通过内容寻址和元数据服务支持不同粒度的数据访问。这些存储系统都在设计中考虑了局部性原则,为上层应用优化提供了支持。
内存管理技术通过高效的缓存机制支持数据局部性。从操作系统的页缓存(Page Cache)到JVM的堆管理,再到专用的堆外内存(Off-heap Memory)设计,不同级别的内存管理技术共同构成了多层次的缓存体系。Spark的统一内存管理器(Unified Memory Manager)动态平衡存储和执行内存,根据工作负载特性优化缓存使用;而Flink的托管内存(Managed Memory)则提供了更细粒度的控制,支持不同算子的局部性优化。
实现技术方面,列式存储是数据局部性优化的关键技术之一。Apache Parquet、ORC和Arrow等格式通过按列组织数据,优化了分析查询的数据访问模式。这些格式还支持谓词下推和统计信息收集,为查询引擎提供更多优化机会。MapReduce的Combiner机制和Spark的map-side聚合都是计算下推的经典实现,通过在数据源头预处理减少后续传输量。
任务调度算法直接决定了计算与数据的匹配程度。YARN的延迟调度(Delay Scheduling)机制允许任务等待一段时间以获得更好的数据局部性;Kubernetes的Pod亲和性(Affinity)规则可以指导容器调度系统考虑数据位置;而新兴的云原生调度框架如Volcano更进一步,提供了更复杂的感知数据分布的调度策略,适应混合工作负载场景。
在应用系统中,数据局部性优化无处不在。Spark SQL优化器分析查询并生成考虑数据局部性的物理计划;HBase的RegionServer设计充分利用数据局部性提供低延迟访问;ElasticSearch和Solr等搜索引擎通过分片和路由机制确保查询效率;而TiDB、CockroachDB等NewSQL数据库则将局部性考量融入分布式事务设计,在保证强一致性的同时提供优化的性能。
未来的发展趋势包括更智能的自适应优化、硬件感知的局部性设计以及面向异构计算环境的局部性策略。随着AI/ML工作负载在大数据系统中的比重增加,针对这类应用特点的局部性优化将成为新的研究热点。同时,边缘计算和5G网络的普及也为数据局部性优化提出了新的挑战和机遇,需要在更广泛的地理分布环境中重新思考计算与数据的关系。
参考资料
[1] Zaharia, M., Chowdhury, M., Das, T., Dave, A., Ma, J., McCauly, M., Franklin, M.J., Shenker, S. and Stoica, I. Resilient Distributed Datasets: A Fault-Tolerant Abstraction for In-Memory Cluster Computing. NSDI 2012.
[2] Dean, J. and Ghemawat, S. MapReduce: Simplified Data Processing on Large Clusters. OSDI 2004.
[3] Armbrust, M., Xin, R.S., Lian, C., Huai, Y., Liu, D., Bradley, J.K., Meng, X., Kaftan, T., Franklin, M.J., Ghodsi, A. and Zaharia, M. Spark SQL: Relational Data Processing in Spark. SIGMOD 2015.
[4] Shvachko, K., Kuang, H., Radia, S. and Chansler, R. The Hadoop Distributed File System. IEEE 2010.
[5] Li, H., Ghodsi, A., Zaharia, M., Shenker, S. and Stoica, I. Tachyon: Reliable, Memory Speed Storage for Cluster Computing Frameworks. SoCC 2014.
被引用于
[1] Spark-SQL查询优化
[2] HBase-性能分析方法论
[3] Iceberg-读取性能优化