Uh oh!
There was an error while loading. Please reload this page.
[SPARK-17409] [SQL] Do Not Optimize Query in CTAS More Than Once - #15048
[SPARK-17409] [SQL] Do Not Optimize Query in CTAS More Than Once#15048gatorsmile wants to merge 5 commits into
Conversation
SparkQA
commented
Sep 11, 2016
Test build #65217 has finished for PR 15048 at commit
|
gatorsmile
commented
Sep 11, 2016
| override def output: Seq[Attribute] = Seq.empty[Attribute] | ||
| override def children: Seq[LogicalPlan] = query.toSeq | ||
| override def children: Seq[LogicalPlan] = Seq.empty[LogicalPlan] |
hvanhovell
commented
Sep 11, 2016
@gatorsmile so should we check all commands? It might also be an idea to have |
gatorsmile
commented
Sep 11, 2016
@hvanhovell Sure, will do it. Thanks! |
SparkQA
commented
Sep 12, 2016
Test build #65233 has finished for PR 15048 at commit
|
| @@ -68,7 +68,7 @@ class ResolveDataSource(sparkSession: SparkSession) extends Rule[LogicalPlan] { | |||
| /** | |||
| * Preprocess some DDL plans, e.g. [[CreateTable]], to do some normalization and checking. | |||
There was a problem hiding this comment.
we should update the comments to say that this rule will also analyze the query.(we may also wanna update the rule name)
There was a problem hiding this comment.
Sure, let me do it now. Thanks!
SparkQA
commented
Sep 13, 2016
Test build #65283 has finished for PR 15048 at commit
|
cloud-fan
commented
Sep 14, 2016
thanks, merging to master! |
### What changes were proposed in this pull request? As explained in apache#14797: >Some analyzer rules have assumptions on logical plans, optimizer may break these assumption, we should not pass an optimized query plan into QueryExecution (will be analyzed again), otherwise we may some weird bugs. For example, we have a rule for decimal calculation to promote the precision before binary operations, use PromotePrecision as placeholder to indicate that this rule should not apply twice. But a Optimizer rule will remove this placeholder, that break the assumption, then the rule applied twice, cause wrong result. We should not optimize the query in CTAS more than once. For example, ```Scala spark.range(99, 101).createOrReplaceTempView("tab1") val sqlStmt = "SELECT id, cast(id as long) * cast('1.0' as decimal(38, 18)) as num FROM tab1" sql(s"CREATE TABLE tab2 USING PARQUET AS $sqlStmt") checkAnswer(spark.table("tab2"), sql(sqlStmt)) ``` Before this PR, the results do not match ``` == Results == !== Correct Answer - 2 == == Spark Answer - 2 == ![100,100.000000000000000000] [100,null] [99,99.000000000000000000] [99,99.000000000000000000] ``` After this PR, the results match. ``` +---+----------------------+ |id |num | +---+----------------------+ |99 |99.000000000000000000 | |100|100.000000000000000000| +---+----------------------+ ``` In this PR, we do not treat the `query` in CTAS as a child. Thus, the `query` will not be optimized when optimizing CTAS statement. However, we still need to analyze it for normalizing and verifying the CTAS in the Analyzer. Thus, we do it in the analyzer rule `PreprocessDDL`, because so far only this rule needs the analyzed plan of the `query`. ### How was this patch tested? Added a test Author: gatorsmile <gatorsmile@gmail.com> Closesapache#15048 from gatorsmile/ctasOptimized.
yhuai
commented
Oct 12, 2016
@gatorsmile We should also backport this to branch 2.0, right? |
yhuai
commented
Oct 12, 2016
@gatorsmile Also, does it affect |
gatorsmile
commented
Oct 12, 2016
Yeah. We should backport it to 2.0 Yeah. It affects both data source tables and hive serde tables. To fix it in Spark 2.0, we need to rewrite the fix since Spark 2.0 does not have a unified logical plan, afaik. Let me submit a PR to backport it. |
yhuai
commented
Oct 12, 2016
Thanks! btw, does this patch cover hive tables? |
yhuai
commented
Oct 12, 2016
Also, another good test for this is Without this fix, you will have an exception like |
yhuai
commented
Oct 12, 2016
Also, can we add a test for hive tables? |
gatorsmile
commented
Oct 12, 2016
Yeah, based on my understanding, it should cover the hive serde table. I will submit a PR to make sure it and also include the test case you provided above. Thank you! |
…15048 ### What changes were proposed in this pull request? This PR is to backport #15048 and #15459. However, in 2.0, we do not have a unified logical node `CreateTable` and the analyzer rule `PreWriteCheck` is also different. To minimize the code changes, this PR adds a new rule `AnalyzeCreateTableAsSelect`. Please treat it as a new PR to review. Thanks! As explained in #14797: >Some analyzer rules have assumptions on logical plans, optimizer may break these assumption, we should not pass an optimized query plan into QueryExecution (will be analyzed again), otherwise we may some weird bugs. For example, we have a rule for decimal calculation to promote the precision before binary operations, use PromotePrecision as placeholder to indicate that this rule should not apply twice. But a Optimizer rule will remove this placeholder, that break the assumption, then the rule applied twice, cause wrong result. We should not optimize the query in CTAS more than once. For example, ```Scala spark.range(99, 101).createOrReplaceTempView("tab1") val sqlStmt = "SELECT id, cast(id as long) * cast('1.0' as decimal(38, 18)) as num FROM tab1" sql(s"CREATE TABLE tab2 USING PARQUET AS $sqlStmt") checkAnswer(spark.table("tab2"), sql(sqlStmt)) ``` Before this PR, the results do not match ``` == Results == !== Correct Answer - 2 == == Spark Answer - 2 == ![100,100.000000000000000000] [100,null] [99,99.000000000000000000] [99,99.000000000000000000] ``` After this PR, the results match. ``` +---+----------------------+ |id |num | +---+----------------------+ |99 |99.000000000000000000 | |100|100.000000000000000000| +---+----------------------+ ``` In this PR, we do not treat the `query` in CTAS as a child. Thus, the `query` will not be optimized when optimizing CTAS statement. However, we still need to analyze it for normalizing and verifying the CTAS in the Analyzer. Thus, we do it in the analyzer rule `PreprocessDDL`, because so far only this rule needs the analyzed plan of the `query`. ### How was this patch tested? Author: gatorsmile <gatorsmile@gmail.com> Closes#15502 from gatorsmile/ctasOptimize2.0.
… Once ### What changes were proposed in this pull request? This follow-up PR is for addressing the [comment](apache#15048). We added two test cases based on the suggestion from yhuai . One is a new test case using the `saveAsTable` API to create a data source table. Another is for CTAS on Hive serde table. Note: No need to backport this PR to 2.0. Will submit a new PR to backport the whole fix with new test cases to Spark 2.0 ### How was this patch tested? N/A Author: gatorsmile <gatorsmile@gmail.com> Closesapache#15459 from gatorsmile/ctasOptimizedTestCases.
… Once ### What changes were proposed in this pull request? This follow-up PR is for addressing the [comment](apache#15048). We added two test cases based on the suggestion from yhuai . One is a new test case using the `saveAsTable` API to create a data source table. Another is for CTAS on Hive serde table. Note: No need to backport this PR to 2.0. Will submit a new PR to backport the whole fix with new test cases to Spark 2.0 ### How was this patch tested? N/A Author: gatorsmile <gatorsmile@gmail.com> Closesapache#15459 from gatorsmile/ctasOptimizedTestCases.
… Once ### What changes were proposed in this pull request? This follow-up PR is for addressing the [comment](apache#15048). We added two test cases based on the suggestion from yhuai . One is a new test case using the `saveAsTable` API to create a data source table. Another is for CTAS on Hive serde table. Note: No need to backport this PR to 2.0. Will submit a new PR to backport the whole fix with new test cases to Spark 2.0 ### How was this patch tested? N/A Author: gatorsmile <gatorsmile@gmail.com> Closesapache#15459 from gatorsmile/ctasOptimizedTestCases.
## What changes were proposed in this pull request? We could get incorrect results by running DecimalPrecision twice. This PR resolves the original found in apache#15048 and apache#14797. After this PR, it becomes easier to change it back using `children` instead of using `innerChildren`. ## How was this patch tested? The existing test. Author: gatorsmile <gatorsmile@gmail.com> Closesapache#20000 from gatorsmile/keepPromotePrecision.
What changes were proposed in this pull request?
As explained in #14797:
We should not optimize the query in CTAS more than once. For example,
Before this PR, the results do not match
After this PR, the results match.
In this PR, we do not treat the
queryin CTAS as a child. Thus, thequerywill not be optimized when optimizing CTAS statement. However, we still need to analyze it for normalizing and verifying the CTAS in the Analyzer. Thus, we do it in the analyzer rulePreprocessDDL, because so far only this rule needs the analyzed plan of thequery.How was this patch tested?
Added a test