【SparkSQL】partitionColumn, lowerBound, upperBound, numPartitions的理解

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wk1134314305/article/details/79055078

如何加快数据的读取过程
利用SparkSQL读取数据库数据的时候,如果数据量很大,那么在读取数据的时候就会花费大量的时间,因此,怎么让数据并行读取加快读取数据的速度呢?

在SparkSQL中,读取数据的时候可以分块读取。例如下面这样,指定了partitionColumn,lowerBound,upperBound,numPartitions等读取数据的参数。

关于这四个参数的意思,SparkSQL官方解释是:

Property Name Meaning
partitionColumn, lowerBound, upperBound These options must all be specified if any of them is specified. In addition, numPartitions must be specified. They describe how to partition the table when reading in parallel from multiple workers. partitionColumn must be a numeric column from the table in question. Notice that lowerBound and upperBound are just used to decide the partition stride, not for filtering the rows in table. So all rows in the table will be partitioned and returned. This option applies only to reading.
numPartitions The maximum number of partitions that can be used for parallelism in table reading and writing. This also determines the maximum number of concurrent JDBC connections. If the number of partitions to write exceeds this limit, we decrease it to this limit by calling coalesce(numPartitions) before writing.
public static Dataset<Row> sparkLoad(SparkSession spark, String url, String fullTable, 
            String partitionColumn, long lowerBound, long upperBound, int numPartitions) {
        DataFrameReader reader = spark.read().format("jdbc").option("url", url)
                .option("dbtable", fullTable).option("user", "postgres")
                .option("driver","org.postgresql.Driver")
                .option("password", "webgis327");
        if(partitionColumn != null){
            reader = reader.option("partitionColumn", partitionColumn)
                          .option("lowerBound", lowerBound)
                          .option("upperBound", upperBound)
                          .option("numPartitions", numPartitions);
        }
        return reader.load();
    }

从上面的解释来看,分区列得是数字类型;所谓的并行读取其实就是开了多个数据库连接,分块读取的。另外需要注意的是:

Notice that lowerBound and upperBound are just used to decide the partition stride, not for filtering the rows in table. So all rows in the table will be partitioned and returned.

也就是说,这些参数的设置不会过滤数据,所以sql中读取了多少数据,那么返回的就是多少条数据,lowerBound和upperBound并不会过滤数据。那么如果说设置的lowerBound偏大(可能读取的数据中分区列的值比这个小),或者设置的upperBound数值设置的大小偏小(可能读取的数据中分区列中最大的值比upperBound大),这个时候数据是怎么读取和返回的呢?

举个例子:

如果一个表分10个分区读取,id为分区列,其值从0-101,但是设置的lowerBound是1,upperBound是100,那么读取的规则如下:
第一个分区:select * from tablename where id<=10;
第二个分区:select * from tablename where id >=10 and id<20;
第三个分区:select * from tablename where id >=20 and id <30;
……
第十个分区:select * from tablename where id >=90;

这样查询不会遗漏结果,但是至于上面的边界条件,等于号是在左边还是在右边这个还不太清楚,笔者也没有研究。其实这个如果要研究的话,也很简单,用一个测试表分区后,分别读取每个分区的数据条数并打印输出,就可以知道了。
思路如下:
读取每个partition的数据数量
但是笔者觉得没有研究的必要,如果对项目没有任何bug上的影响,就不需要研究这么细节,对技术没有什么帮助。

猜你喜欢

转载自blog.csdn.net/wk1134314305/article/details/79055078