apache-spark - 查询需要很长时间'选择'什么
问题描述
我有一个查询,我在节俭中运行了很长时间。我在具有 500k 行的表的单个分区上运行它。
查询如下所示:
select col0 from <table> where partition=<partition> and <col1>=<val>
我做到了col1 != val
,所以查询返回 0 行。
此查询大约需要 30 秒(如果我使用,则为一分钟select *
)。
当我运行完全相同的查询但select count(col0)
需要 2 秒时。
什么可能导致查询需要很长时间select col
而不是select count(col)
?
这是解释的查询
explain select col0 from table where `partition` = partition and col=val;
*Project [col0#607]
+- *Filter (isnotnull(col1#607) && (col1#607 = aaaa))
+- *FileScan parquet
table[col1#607,partition#611]
批处理:true,
格式:Parquet,
位置:PrunedInMemoryFileIndex[...,
PartitionCount:23,
PartitionFilters:[isnotnull(partition#611),
(cast(partition#611 as int) = partition_name)],
PushedFilters:[IsNotNull(col1),
EqualTo(col1,aaaa) ],
ReadSchema:结构
explain select count(col0) from table where `partition` = partition and col=val;
*HashAggregate(keys=[], functions=[count(col0#625)])
+- Exchange SinglePartition
+- *HashAggregate(keys=[], functions=[partial_count(col0#625)])
+- *Project [col0 #625]
+- *Filter (isnotnull(col1#625) && (col1#625 = aaaa))
+- *FileScan parquet
table[col1#625,partition#629] 批处理:true,
格式:Parquet,
位置:PrunedInMemoryFileIndex[ ...,
PartitionCount: 23,
PartitionFilters: [isnotnull(partition#629),
(cast(partition#629 as int) = partition_name)],
PushedFilters: [IsNotNull(col1),
EqualTo(col1,aaaa)],
读取架构:结构
据我所知,过程完全一样,只是count
查询有更多的步骤。那么它为什么快 15 倍呢?
编辑:
我在日志中发现了这个有趣的块:
与计数:
18/06/28 11:42:55 INFO TaskSetManager:在阶段 2509.0 启动任务 0.0(TID 8092,ip-123456,执行器 36,分区 0,RACK_LOCAL,5521 字节)
28/06 11:42:55 INFO TaskSetManager :在阶段 2509.0 中启动任务 1.0(TID 8093,ip-123456,执行程序 35,分区 1,RACK_LOCAL,5521 字节)
18/06/28 11:42:55 INFO TaskSetManager:在阶段 2509.0 中启动任务 2.0(TID 8094,ip -123456,执行程序 36,分区 2,RACK_LOCAL,5521 字节)
18/06/28 11:42:55 信息 TaskSetManager:在阶段 2509.0 中启动任务 3.0(TID 8095,ip-123456,执行程序 35,分区 3,RACK_LOCAL,5521字节)
18/06/28 11:42:55 INFO TaskSetManager:在阶段 2509.0 启动任务 4.0(TID 8096,ip-123456,执行程序 36,分区 4,RACK_LOCAL,5521 字节)
18/06/28 11:42:55 INFO TaskSetManager:在阶段 2509.0 启动任务 5.0(TID 8097,ip-123456,执行程序 35,分区 5,RACK_LOCAL,5521 字节)
28/06/18 11:42:55 INFO TaskSetManager :在阶段 2509.0 中启动任务 6.0(TID 8098,ip-123456,执行程序 36,分区 6,RACK_LOCAL,5521 字节)
18/06/28 11:42:55 INFO TaskSetManager:在阶段 2509.0 中启动任务 7.0(TID 8099,ip -123456,执行程序 35,分区 7,RACK_LOCAL,5521 字节)
18/06/28 11:42:55 信息 TaskSetManager:在阶段 2509.0 启动任务 8.0(TID 8100,ip-123456,执行程序 36,分区 8,RACK_LOCAL,5521字节)
18/06/28 11:42:55 INFO TaskSetManager:在阶段 2509.0 启动任务 9.0(TID 8101,ip-123456,执行程序 35,分区 9,RACK_LOCAL,5521 字节)
- 没有: *
18/06/28 11:45:32 INFO TaskSetManager:在阶段 2512.0 中启动任务 0.0(TID 8136,ip-10-117-49-97.eu-west-1.compute.internal,执行程序 37,分区 1,RACK_LOCAL , 5532 字节)
18/06/28 11:45:32 INFO BlockManagerInfo:在内存中添加了广播_2352_piece0 ip-10-117-49-97.eu-west-1.compute.internal:40489(大小:12.6 KB,免费: 11.6 GB)
18/06/28 11:45:32 INFO TaskSetManager: 在 ip-10-117-49-97.eu-west-1.compute.internal 的 667 毫秒内完成阶段 2512.0 (TID 8136) 中的任务 0.0 (执行者 37)(1/1)
18/06/28 11:45:32 INFO YarnScheduler:从池 18/06/28 11:45:32 中删除了 TaskSet 2512.0,其任务已全部完成,
INFO DAGScheduler:ResultStage 2512( OperationManager.java:220 处的 getNextRowSet)在 0.668 秒内完成
28 年 6 月 18 日 11:45:32 信息 DAGScheduler:作业 2293 完成:OperationManager.java:220 处的 getNextRowSet,耗时 0.671740 秒
18/06/28 11:45:32 信息 SparkContext:开始作业:OperationManager.java 处的 getNextRowSet: 220
18/06/28 11:45:32 INFO DAGScheduler:得到作业 2294 (getNextRowSet at OperationManager.java:220) 1 输出分区
18/06/28 11:45:32 INFO DAGScheduler:最后阶段:ResultStage 2513 (getNextRowSet在 OperationManager.java:220)
18/06/28 11:45:32 信息 DAGScheduler:最后阶段的父母:List()
18/06/28 11:45:32 信息 DAGScheduler:失踪父母:List()
18/06 /28 11:45:32 INFO DAGScheduler: 提交 ResultStage 2513 (MapPartitionsRDD[312] at run at AccessController.java:0),没有丢失的父母
18/06/28 11:45:32 INFO MemoryStore:块 broadcast_2353 存储为内存中的值(估计大小 66.6 KB,空闲 12.1 GB)
18/06/28 11:45:32 INFO MemoryStore:块 broadcast_2353_piece0 存储为内存中的字节(估计大小 12.6 KB,免费 12.1 GB)
18/06/28 11:45:32 INFO BlockManagerInfo:在内存中添加了广播_2353_piece0 10.117.48.68:41493(大小:12.6 KB,免费:12.1 GB)
18/06/28 11 :45:32 INFO SparkContext:从 DAGScheduler.scala:1047 18/06/28 11:45:32 的广播创建广播 2353
信息 DAGScheduler:从 ResultStage 2513 提交 1 个丢失的任务(MapPartitionsRDD [312] 在 AccessController.java 运行时: 0)(前 15 个任务用于分区
Vector(2))18/06/28 11:45:32 INFO YarnScheduler:添加任务集 2513.0 和 1 个任务
28 年 6 月 18 日 11:45:32 信息 TaskSetManager:在阶段 2513.0 中启动任务 0.0(TID 8137,ip-10-117-49-97.eu-west-1.compute.internal,执行程序 37,分区 2,RACK_LOCAL , 5532 字节)
18/06/28 11:45:33 INFO BlockManagerInfo:在内存中添加了广播_2353_piece0 ip-10-117-49-97.eu-west-1.compute.internal:40489(大小:12.6 KB,免费: 11.6 GB)
18/06/28 11:45:38 INFO TaskSetManager: 在 ip-10-117-49-97.eu-west-1.compute.internal 的 5238 毫秒内完成阶段 2513.0 (TID 8137) 中的任务 0.0 (执行者 37)(1/1)
18/06/28 11:45:38 INFO YarnScheduler:从池 18/06/28 11:45:38 中删除了 TaskSet 2513.0,其任务已全部完成,
INFO DAGScheduler:ResultStage 2513( OperationManager.java:220 处的 getNextRowSet)在 5.238 秒内完成
28 年 6 月 18 日 11:45:38 信息 DAGScheduler:作业 2294 完成:OperationManager.java:220 的 getNextRowSet,耗时 5.242084 秒
28 年 6 月 18 日 11:45:38 信息 SparkContext:开始作业:OperationManager.java 的 getNextRowSet: 220
18/06/28 11:45:38 INFO DAGScheduler:得到作业 2295(在 OperationManager.java:220 上的 getNextRowSet),带有 1 个输出分区
18/06/28 11:45:38 INFO DAGScheduler:最后阶段:ResultStage 2514(getNextRowSet在 OperationManager.java:220)
18/06/28 11:45:38 信息 DAGScheduler:最后阶段的父母:List()
18/06/28 11:45:38 信息 DAGScheduler:失踪父母:List()
18/06 /28 11:45:38 INFO DAGScheduler: 提交 ResultStage 2514 (MapPartitionsRDD[312] at run at AccessController.java:0), 没有丢失的父母
18/06/28 11:45:38 INFO MemoryStore:块 broadcast_2354 作为值存储在内存中(估计大小 66.6 KB,空闲 12.1 GB)
18/06/28 11:45:38 INFO MemoryStore:块 broadcast_2354_piece0 作为字节存储在内存中(估计大小 12.6 KB,免费 12.1 GB)
18/06/28 11:45:38 INFO BlockManagerInfo:在内存中添加了广播_2354_piece0 10.117.48.68:41493(大小:12.6 KB,免费:12.1 GB)
18/06/28 11 :45:38 INFO SparkContext:从 DAGScheduler.scala:1047 18/06/28 11:45:38 的广播创建广播 2354
信息 DAGScheduler:从 ResultStage 2514 提交 1 个丢失的任务(MapPartitionsRDD [312] 在 AccessController.java 运行时: 0)(前 15 个任务用于分区 Vector(3))
(即它重复这个块,看起来它顺序运行任务而不是像计数情况那样并行)
我也尝试过“order by”,它实际上使查询运行速度提高了 2倍
使用 spark 而不是 thrift 对相同数据运行相同的查询要快得多。
我在 aws emr-5.11.1 上运行节俭
蜂巢 2.3.2
火花 2.2.1
节俭 0.11.0
解决方案
发现了问题。我有这面旗帜
spark.sql.thriftServer.incrementalCollect=true
在节俭服务器中。它按顺序收集每个工作人员的输出,这就是造成如此巨大开销的原因。删除标志解决了这个问题。我猜它被优化为在做“计数”时不做顺序,因为它不一定有很多数据。
推荐阅读
- eclipse - Ceylon 运行配置:找不到项目
- angular - 角度渲染链接
- sql - 如何使用活动记录而不是数组从用户那里获取任务列表
- android - 如何动态更改 addOnScrollChangedListener 中 ImageView 的大小?
- javascript - 在javascript中按多个对象属性对数组进行排序
- android - 在滚动视图中不出现任何内容
- angular - 如何正确地将谷歌地图库导入角度应用程序
- java - Android 热点无法在某些设备上运行
- struts2 - Struts2 包命名空间继承
- go - 在 Go 的父目录中递归查找具有名称的文件