基于ORA_HASH的Spark多分区读取Oracle数据的技术疑问
问题解答
问题1:Oracle查询的内部执行逻辑
Oracle对该查询的执行是逐行流水线式处理,既不是先对所有c列值计算哈希再过滤,也不是先提取所有a、b、c列再处理:
- 首先,Oracle扫描
Table_1的行数据,逐行读取当前行的t.a、t.b、t.c三个列的值; - 接着,对当前行的
t.c执行CAST(...) AS NUMBER(38)转换,再调用ORA_HASH计算哈希值得到hashedID; - 最后,将当前行的
t.a、t.b和计算出的hashedID作为结果行输出。
如果后续加上WHERE hashedID = X的过滤条件,Oracle会在计算出当前行的hashedID后立即判断是否符合条件,符合条件才会输出该行的t.a、t.b,不会先生成所有行的哈希结果再过滤。
问题2:Spark并行分区读取的执行方式与冗余计算判断
你的理解完全正确,Spark的每个executor确实会执行类似你给出的嵌套查询:
select a, b from (select t.a, t.b, ORA_HASH(CAST((t.c) AS NUMBER(38)), 7) as hashedID from Table_1 t) where hashedID = 3
对应的冗余计算判断也准确:每个executor发起的JDBC连接都会让Oracle重新扫描全表,逐行计算t.c的哈希值,再过滤出对应分区的结果。8个分区就意味着Oracle要对Table_1执行8次全表扫描+哈希计算,这会造成巨大的资源浪费,也是导致Oracle TEMP表空间耗尽的重要原因之一——重复的全表扫描和哈希计算会持续占用临时空间,叠加后超出阈值。
内容的提问来源于stack exchange,提问作者Devdatta
相关产品推荐
相关产品推荐

