Sql server Spark\u秩窗口函数-不带partitionBy子句

Sql server Spark\u秩窗口函数-不带partitionBy子句,sql-server,scala,apache-spark,yarn,hadoop2,Sql Server,Scala,Apache Spark,Yarn,Hadoop2,我使用的是Spark 1.6.2、Scala 2.10.5和Java1.7 我们的用例要求我们对超过2亿行的数据集执行稠密的_rank(),而不使用partitionBy子句,只使用orderBy子句。这目前在MSSQL中运行,大约需要30分钟才能完成 我在Spark中实现了如下所示的等效逻辑: val df1 = hqlContext.read.format("jdbc").options( Map("url" -> url, "driver" -> driver, "db

我使用的是Spark 1.6.2、Scala 2.10.5和Java1.7

我们的用例要求我们对超过2亿行的数据集执行稠密的_rank(),而不使用partitionBy子句,只使用orderBy子句。这目前在MSSQL中运行,大约需要30分钟才能完成

我在Spark中实现了如下所示的等效逻辑:

val df1 = hqlContext.read.format("jdbc").options(
  Map("url" -> url, "driver" -> driver,
  "dbtable" -> "(select * from OwnershipStandardization_PositionSequence_tbl) as ps")).load()

df1.cache()

val df1_drnk = df1.withColumn("standardizationId",denseRank().over(Window.orderBy("ownerObjectId","securityId","periodId")))
我提交的纱线集群模式的工作如下所示。我有一个2节点的Hadoop 2.6集群,每个集群有4个vCore和32 GB内存

spark-submit --class com.spgmi.csd.OshpStdCarryOver --master  yarn --deploy-mode cluster --conf spark.yarn.executor.memoryOverhead=3072 --num-executors 2 --executor-cores 3 --driver-memory 7g --executor-memory 16g --jars $SPARK_HOME/lib/datanucleus-api-jdo-3.2.6.jar,$SPARK_HOME/lib/datanucleus-core-3.2.10.jar,$SPARK_HOME/lib/datanucleus-rdbms-3.2.9.jar,/usr/share/java/sqljdbc_4.1/enu/sqljdbc41.jar --files $SPARK_HOME/conf/hive-site.xml $SPARK_HOME/lib/spark-poc2-14.0.0.jar
在日志中,我可以看到MSSQL中大约2亿行的表在15分钟内被导入并缓存到Spark中。在这个阶段之前,我看到大约有5 GB的内存被使用,其中一个执行器上大约有6.2 GB的内存可用,而另一个执行器上有11 GB的内存可用

但是,稠密_rank()的步骤总是失败,几分钟后出现“超出GC开销限制”错误。我甚至将驱动程序内存设置为7g,正如您在上面的spark submit命令中所注意到的那样。但是,没有用!。 当然,我知道缺少partitionBy条款实际上在Spark中造成了麻烦。但是,不幸的是,这是我们需要处理的用例

你能不能在这里再亮一点?我错过什么了吗?在Spark中使用稠密_秩窗口函数有其他选择吗?比如,使用本论坛其他专家建议的“zipWithIndex”功能?按照我的理解,“zipWithIndex”方法复制的是row_number()函数,而不是densite_rank,它会产生与densite_rank相同的结果吗

任何有用的建议都将不胜感激!
非常感谢

这里有两个不同的问题:

  • 您可以通过JDBC连接加载数据,而不提供分区列或分区谓词。这将使用单个执行器线程加载所有数据

    这个问题通常很容易解决,可以使用现有列之一,也可以提供人工键

  • 您使用的窗口函数没有
    partitionBy
    。因此,所有数据都被重新排列到单个分区,在本地进行排序,并使用单个线程进行处理

    一般来说,没有通用的解决方案可以仅使用
    Dataset
    API解决此问题,但您可以使用以下技巧:

    • 创建反映所需记录顺序的人工分区。我在回答问题时描述了这种方法

      在您的案例中也可以使用类似的方法,但它需要多步骤的过程,相当于下面描述的过程

    • 使用关联方法,您可以对排序后的
      RDD
      使用两个单独的扫描(也可以在不从
      数据集转换的情况下执行类似操作)和其他操作:

      • 计算每个分区的部分结果(在您的例子中,是给定分区的秩)
      • 收集所需的摘要(在您的例子中是分区边界和每个分区的累积秩值)
      • 执行第二次扫描以更正前面分区中的部分聚合
    这种方法的一个例子可以很容易地根据您的情况进行调整,可以在中找到


非常感谢您的建议!我能够使用JDBC数据源中的“partitionColumn”选项减少从MSSQL导入数据的时间。但是,对于没有分区的密集排名的建议,我需要更多的时间来消化,因为我对Scala还很陌生。但是,非常感谢你指导我!