Uh oh!
There was an error while loading. Please reload this page.
[SPARK-12355][SQL] Implement unhandledFilter interface for Parquet - #10502
[SPARK-12355][SQL] Implement unhandledFilter interface for Parquet#10502HyukjinKwon wants to merge 10 commits into
Conversation
SparkQA
commented
Dec 29, 2015
Test build #48396 has finished for PR 10502 at commit
|
HyukjinKwon
commented
Dec 29, 2015
The test is failed from wrong results from Parquet. As can be seen, |
HyukjinKwon
commented
Dec 29, 2015
I see. I think I should disable |
SparkQA
commented
Dec 29, 2015
Test build #48403 has finished for PR 10502 at commit
|
SparkQA
commented
Dec 29, 2015
Test build #48402 has finished for PR 10502 at commit
|
SparkQA
commented
Dec 29, 2015
Test build #48405 has finished for PR 10502 at commit
|
HyukjinKwon
commented
Dec 29, 2015
yhuai
commented
Dec 29, 2015
@HyukjinKwon Thank you for the PR? Can you post some benchmarking results (with your testing code)? It will be good to have these numbers to help others understand if it can provide benefit. |
HyukjinKwon
commented
Dec 29, 2015
@yhuai Sure. I will try! |
HyukjinKwon
commented
Dec 30, 2015
Benchmark (Removed Spark-side Filter)MotivationThis PR simplifies the query plans for Parquet files by stripping duplicated Spark-side filtering, from: to : However, in terms of performance, it is unkown if there is benefit. So, this benchmark was performed. Environment
Method
DatasetRaw Data
Create Target Parquet File
caseclassLineitem(l_orderkey: Int,
l_partkey: Int,
l_suppkey: Int,
l_linenumber: Int,
l_quantity: Float,
l_extendedprice: Float,
l_discount: Float,
l_tax: Float,
l_returnflag: String,
l_linestatus: String,
l_shipdate: String,
l_commitdate: String,
l_receiptdate: String,
l_shipinstruct: String,
l_shipmode: String,
l_comment: String)
importsqlContext.implicits._varconf=newSparkConf()
conf.setAppName("Test").setMaster("local")
conf.set("spark.sql.parquet.compression.codec", "uncompressed")
valsc=newSparkContext(conf)
valsqlContext=new org.apache.spark.sql.SQLContext(sc)
sc.textFile("lineitem.tbl").map(_.split('|')).map { v =>Lineitem(
v(0).trim.toInt,
v(1).trim.toInt,
v(2).trim.toInt,
v(3).trim.toInt,
v(4).trim.toFloat,
v(5).trim.toFloat,
v(6).trim.toFloat,
v(7).trim.toFloat,
v(8),
v(9),
v(10),
v(11),
v(12),
v(13),
v(14),
v(15))
}.toDF()
df.save("lineitem", "parquet")Parquet fileTest Codes
deftime[A](f: =>A) = {
vals=System.nanoTime
valret= f
println("time: "+(System.nanoTime-s)/1e6+"ms")
ret
}
varconf=newSparkConf()
conf.setAppName("Test").setMaster("local")
conf.set("spark.sql.parquet.enableUnsafeRowRecordReader", "false")
valsc=newSparkContext(conf)
valsqlContext=new org.apache.spark.sql.SQLContext(sc)
valsource= sqlContext.read.parquet("lineitem")
valdf= source.filter("l_orderkey IS NULL").select("l_orderkey")
time(df.collect())
valsource= sqlContext.read.parquet("lineitem")
valdf= source.filter("l_orderkey IS NOT NULL").select("l_orderkey")
time(df.collect())
valsource= sqlContext.read.parquet("lineitem")
valdf= source.filter("l_orderkey = 1").select("l_orderkey")
time(df.collect())
valsource= sqlContext.read.parquet("lineitem")
valdf= source.filter("l_orderkey != 1").select("l_orderkey")
time(df.collect())
valsource= sqlContext.read.parquet("lineitem")
valdf= source.filter("l_orderkey <=> 1").select("l_orderkey")
time(df.collect())
valsource= sqlContext.read.parquet("lineitem")
valdf= source.filter("l_orderkey < 3000000").select("l_orderkey")
time(df.collect())
valsource= sqlContext.read.parquet("lineitem")
valdf= source.filter("l_orderkey > 3000000").select("l_orderkey")
time(df.collect())
valsource= sqlContext.read.parquet("lineitem")
valdf= source.filter("l_orderkey <= 3000000").select("l_orderkey")
time(df.collect())
valsource= sqlContext.read.parquet("lineitem")
valdf= source.filter("l_orderkey >= 3000000").select("l_orderkey")
time(df.collect())Results
Basically, in a simple view, the difference was below. The original codes would work as below (With Spark Filtering): data
// Parquet-side filtering
.filter(pushedFilter)
// Spark-side filtering
.filter(pushedFilter)This PR would change this into below (Without Spark Filtering): data
// Parquet-side filtering
.filter(pushedFilter)Although both have the same O(n) time complexity, the former was 2n and the latter was n. So, it seems there is performance benefit. One notable thing is, there was still considerable performance differences for So, in conclusion, although we cannot depend only on this benchmark, it seems there is performance benefit approximately from 1% to 4% for basic queries with pushed filters in terms of elapsed time. |
HyukjinKwon
commented
Dec 30, 2015
@yhuai@liancheng@rxin Would you look through this please? |
There was a problem hiding this comment.
Oh, yes it looks so. I think I might also have to change createFilter() in that way because I just followed up in the way of createFilter() for this function because both createFilter() and referencedColumns() are called in the same places.
JoshRosen
commented
Jan 11, 2016
Jenkins, retest this please. |
SparkQA
commented
Jan 11, 2016
Test build #49115 has finished for PR 10502 at commit
|
SparkQA
commented
Jan 11, 2016
Test build #49122 has finished for PR 10502 at commit
|
HyukjinKwon
commented
Feb 5, 2016
I will resolve this conflict on Thursday. |
SparkQA
commented
Feb 11, 2016
Test build #51075 has finished for PR 10502 at commit
|
HyukjinKwon
commented
Feb 11, 2016
@liancheng@yhuai Would you look through this please? |
SparkQA
commented
Feb 26, 2016
Test build #52014 has finished for PR 10502 at commit
|
yhuai
commented
Feb 26, 2016
@HyukjinKwon Thank you for working on it. We have been actively improving the efficiency of code-gen and unsafe parquet reader. For the long term, letting parquet to evaluate filters like |
HyukjinKwon
commented
Feb 26, 2016
@yhuai No problem. Then, please inform me later when I am supposed to do something else. |
yhuai
commented
Feb 26, 2016
yea will do. Thank you. |
@yhuai Let me close this for now. Please let me know although this is closed. I will reopen this when I start to work on this again. |
HyukjinKwon
commented
Jun 17, 2016
Hi @yhuai ! Would this be okay if I give a try for this one again maybe? |
What changes were proposed in this pull request?
https://issues.apache.org/jira/browse/SPARK-12355
This is similar with #10427.
As discussed here #10221, this PR implemented
unhandledFilterto remove duplicated Spark-side filtering.In case of Parquet, the columns referenced in pushed down filters should be given to
org.apache.spark.sql.parquet.row.requested_schemawhereas general datasources such as JDBC do not require the columns.However,
DataSourceStrategy.pruneFilterProjectRaw()removes the columns only referenced in pushed down filters. Therefore, this PR resolved this problem by manually generating the columns referenced in pushed down filters.How was the this patch tested?
This was tested with unittests and with
dev/run_testsfor coding style