-
Notifications
You must be signed in to change notification settings - Fork 29k
[SPARK-29295][SQL] Insert overwrite to Hive external table partition should delete old data #25979
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
| // insert overwrite to the same partition, the partition will have both old and new | ||
| // data. | ||
| val updatedPart = if (overwrite && table.tableType == CatalogTableType.EXTERNAL) { | ||
| AlterTableAddPartitionCommand( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of constructing partition directory manually, I let hive add the target parititon to be overwritten. We will delete the partition directory below.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How can we rollback if the follow loadPartition operation fails?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we provide rollback for load partition before?
|
cc @felixcheung |
|
Test build #111616 has finished for PR 25979 at commit
|
|
How does hive handle it? Does it also produce duplicated data? |
|
As I quickly tried on Hive, Hive does not delete existing directory with "INSERT OVERWRITE", if the external partition was dropped by "DROP PARTITION" before. Hive just moves data from staging into the directory in this case. Whether it produces duplicated data, depending on the filename generated. I tested two version of Hive locally. I do not know the logic Hive produces data filename. On Hive 2.1.0, two "INSERT OVERWRITE" produces data file with same name like 000000_0. The second "INSERT OVERWRITE" moves the file into and overwrite old file. On Hive 2.3.2, the second "INSERT OVERWRITE" causes following failure when moving file with same name: So, I think it is sure that Hive does not delete existing directory when "INSERT OVERWRITE" into a non-existing partition. Whether duplicated data are seen, it depends on if filenames are unique or not between different "INSERT OVERWRITE". If your first "INSERT OVERWRITE" produces filename "000000_0" and "000001_0", but the second "INSERT OVERWRITE" produces just "000000_0", you will read partial old data "000001_0" with new "000000_0" together. Above tests are using MR as Hive execution engine. I am not sure if Hive has different output filename in different execution engine like Spark or Tez. |
|
Do you mean the current behavior is consistent with some Hive versions? |
|
Currently behavior of INSERT OVERWRITE into a Hive external table partition is consistent with Hive. If the partition was dropped by DROP PARTITION before, INSERT OVERWRITE will not overwrite existing partition directory. If there are files in the directory, conflicting files will be overwritten (Hive 2.1) or exception thrown (Hive 2.3.2). Unique files will be read as duplicated data. |
|
yeah, this is a hard one, obviously the behavior is buggy, hard to detect etc. but that's how Hive is designed. I think we should log a warn in Spark at least so interested folks (like us) can detect this after the job is run
we can't really rely on the name being the same to overwrite. it depends on a number of things. for instance, if the original partition has 10B row and 1M file, overwritten with new partition having 1B and 100k file, then a lot of files are not going to be overwritten (like 900k) |
|
or we do
|
|
I am not sure if this is designed behavior of Hive. You can see a similar issue at Hive https://jira.apache.org/jira/browse/HIVE-18702. INSERT OVERWRITE should clean table directory. The last comment in that ticket, someone left a comment describing the same case as this. He said he will create a ticket, but I do not see that. |
|
I think the semantics of INSERT OVERWRITE should be overwriting existing data with new data. By no means it leaves old data intact with new data. I think there are few options in this case:
Any ideas? @cloud-fan @felixcheung |
|
It looks to me we should clean the directory is what the hive community is saying.
…________________________________
From: Liang-Chi Hsieh <notifications@github.com>
Sent: Thursday, October 3, 2019 1:36:59 PM
To: apache/spark <spark@noreply.github.com>
Cc: Felix Cheung <felixcheung_m@hotmail.com>; Mention <mention@noreply.github.com>
Subject: Re: [apache/spark] [SPARK-29295][SQL] Insert overwrite to Hive external table partition should delete old data (#25979)
I think the semantics of INSERT OVERWRITE should be overwriting existing data with new data. By no means it leaves old data intact with new data.
I think there are few options in this case:
1. delete old data like this PR currently did
2. no delete old data, throw an exception to user, saying there are old data. (I think this might be confusing to user. I am also wondering how user can react to this, if they do not access filesystem)
Any ideas? @cloud-fan<https://github.com/cloud-fan> @felixcheung<https://github.com/felixcheung>
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub<#25979?email_source=notifications&email_token=ACENZ6ZBUB7354FYCXP5YVDQMZJWXA5CNFSM4I35N7KKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEAJQIZA#issuecomment-538117220>, or mute the thread<https://github.com/notifications/unsubscribe-auth/ACENZ6YVFGNNKVGFUXH5URTQMZJWXANCNFSM4I35N7KA>.
|
sql/hive/src/test/scala/org/apache/spark/sql/hive/execution/SQLQuerySuite.scala
Outdated
Show resolved
Hide resolved
sql/hive/src/main/scala/org/apache/spark/sql/hive/execution/InsertIntoHiveTable.scala
Outdated
Show resolved
Hide resolved
sql/hive/src/main/scala/org/apache/spark/sql/hive/execution/InsertIntoHiveTable.scala
Outdated
Show resolved
Hide resolved
|
Test build #111876 has finished for PR 25979 at commit
|
|
Test build #111900 has finished for PR 25979 at commit
|
|
Test build #111914 has finished for PR 25979 at commit
|
| val splitPart = part.split("=") | ||
| assert(splitPart.size == 2, s"Invalid written partition path: $part") | ||
| ExternalCatalogUtils.unescapePathName(splitPart(0)) -> | ||
| ExternalCatalogUtils.unescapePathName(splitPart(1)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Regarding some partition values that get escaped, we need to unescape them.
|
Test build #111916 has finished for PR 25979 at commit
|
|
@cloud-fan @felixcheung Do you have more comments on this? |
|
retest this please |
|
Test build #112053 has finished for PR 25979 at commit
|
|
cc @dongjoon-hyun @HyukjinKwon too |
sql/hive/src/main/scala/org/apache/spark/sql/hive/execution/InsertIntoHiveTable.scala
Outdated
Show resolved
Hide resolved
sql/hive/src/main/scala/org/apache/spark/sql/hive/execution/InsertIntoHiveTable.scala
Outdated
Show resolved
Hide resolved
|
Test build #112203 has finished for PR 25979 at commit
|
|
Test build #112204 has finished for PR 25979 at commit
|
|
Test build #112209 has finished for PR 25979 at commit
|
|
thanks, merging to master! |
|
Sorry for late response, @viirya. Looks making sense to me too. |
Hive use Then you insert overwrite into this partition with one file In spark, each result's file name is different....so, data dunplicted. |
|
Hi, @viirya . Since this seems to be a correctness fix, could you make a backport PR to Hi, @AngersZhuuuu . Do you mean that is another corner case existing still? |
|
@dongjoon-hyun Ok. I can prepare a backport PR for 2.4. |
|
Thank you so much, @viirya . |
…tion should delete old data ### What changes were proposed in this pull request? This patch proposes to delete old Hive external partition directory even the partition does not exist in Hive, when insert overwrite Hive external table partition. This is backport of #25979 to branch-2.4. ### Why are the changes needed? When insert overwrite to a Hive external table partition, if the partition does not exist, Hive will not check if the external partition directory exists or not before copying files. So if users drop the partition, and then do insert overwrite to the same partition, the partition will have both old and new data. For example: ```scala withSQLConf(HiveUtils.CONVERT_METASTORE_PARQUET.key -> "false") { // test is an external Hive table. sql("INSERT OVERWRITE TABLE test PARTITION(name='n1') SELECT 1") sql("ALTER TABLE test DROP PARTITION(name='n1')") sql("INSERT OVERWRITE TABLE test PARTITION(name='n1') SELECT 2") sql("SELECT id FROM test WHERE name = 'n1' ORDER BY id") // Got both 1 and 2. } ``` ### Does this PR introduce any user-facing change? Yes. This fix a correctness issue when users drop partition on a Hive external table partition and then insert overwrite it. ### How was this patch tested? Added test. Closes #27887 from viirya/SPARK-29295-2.4. Authored-by: Liang-Chi Hsieh <viirya@gmail.com> Signed-off-by: Dongjoon Hyun <dongjoon@apache.org>
…ion path should be case insensitive ### What changes were proposed in this pull request? This is a follow up of #25979. When we inserting overwrite an external hive partitioned table with upper case dynamic partition key, exception thrown. like: ``` org.apache.spark.SparkException: Dynamic partition key P1 is not among written partition paths. ``` The root cause is that Hive metastore is not case preserving and keeps partition columns with lower cased names, see details in: https://github.com/apache/spark/blob/ddd8d5f5a0b6db17babc201ba4b73f7df91df1a3/sql/hive/src/main/scala/org/apache/spark/sql/hive/HiveExternalCatalog.scala#L895-L901 https://github.com/apache/spark/blob/e28914095aa1fa7a4680b5e4fcf69e3ef64b3dbc/sql/hive/src/main/scala/org/apache/spark/sql/hive/execution/InsertIntoHiveTable.scala#L228-L234 In this PR, we convert the dynamic partition map to a case insensitive map. ### Why are the changes needed? To fix the issue when inserting overwrite into external hive partitioned table with upper case dynamic partition key. ### Does this PR introduce _any_ user-facing change? No. ### How was this patch tested? UT. Closes #28765 from turboFei/SPARK-29295-follow-up. Authored-by: turbofei <fwang12@ebay.com> Signed-off-by: Wenchen Fan <wenchen@databricks.com>
…ion path should be case insensitive ### What changes were proposed in this pull request? This is a follow up of #25979. When we inserting overwrite an external hive partitioned table with upper case dynamic partition key, exception thrown. like: ``` org.apache.spark.SparkException: Dynamic partition key P1 is not among written partition paths. ``` The root cause is that Hive metastore is not case preserving and keeps partition columns with lower cased names, see details in: https://github.com/apache/spark/blob/ddd8d5f5a0b6db17babc201ba4b73f7df91df1a3/sql/hive/src/main/scala/org/apache/spark/sql/hive/HiveExternalCatalog.scala#L895-L901 https://github.com/apache/spark/blob/e28914095aa1fa7a4680b5e4fcf69e3ef64b3dbc/sql/hive/src/main/scala/org/apache/spark/sql/hive/execution/InsertIntoHiveTable.scala#L228-L234 In this PR, we convert the dynamic partition map to a case insensitive map. ### Why are the changes needed? To fix the issue when inserting overwrite into external hive partitioned table with upper case dynamic partition key. ### Does this PR introduce _any_ user-facing change? No. ### How was this patch tested? UT. Closes #28765 from turboFei/SPARK-29295-follow-up. Authored-by: turbofei <fwang12@ebay.com> Signed-off-by: Wenchen Fan <wenchen@databricks.com> (cherry picked from commit 717ec5e) Signed-off-by: Wenchen Fan <wenchen@databricks.com>
What changes were proposed in this pull request?
This patch proposes to delete old Hive external partition directory even the partition does not exist in Hive, when insert overwrite Hive external table partition.
Why are the changes needed?
When insert overwrite to a Hive external table partition, if the partition does not exist, Hive will not check if the external partition directory exists or not before copying files. So if users drop the partition, and then do insert overwrite to the same partition, the partition will have both old and new data.
For example:
Does this PR introduce any user-facing change?
Yes. This fix a correctness issue when users drop partition on a Hive external table partition and then insert overwrite it.
How was this patch tested?
Added test.