Skip to content

[SPARK-38647][SQL] Add SupportsReportOrdering mix in interface for Scan (DataSourceV2) - #35965

Closed
EnricoMi wants to merge 22 commits into
apache:masterfrom
G-Research-Forks:branch-datasourcev2-output-ordering
Closed

[SPARK-38647][SQL] Add SupportsReportOrdering mix in interface for Scan (DataSourceV2)#35965
EnricoMi wants to merge 22 commits into
apache:masterfrom
G-Research-Forks:branch-datasourcev2-output-ordering

Conversation

@EnricoMi

Copy link
Copy Markdown
Contributor

What changes were proposed in this pull request?

As SupportsReportPartitioning allows implementations of Scan provide Spark with information about the exiting partitioning of data read by a DataSourceV2, a similar mix in interface SupportsReportOrdering should provide order information.

Why are the changes needed?

This prevents Spark from sorting data if they already exhibit a certain order provided by the source.

Does this PR introduce any user-facing change?

It adds SupportsReportOrdering mix in interface.

How was this patch tested?

This adds tests to DataSourceV2Suite, similar to the test for SupportsReportPartitioning.

@AmplabJenkins

Copy link
Copy Markdown

Can one of the admins verify this patch?

@EnricoMi
EnricoMiforce-pushed the branch-datasourcev2-output-ordering branch 2 times, most recently from 2efc6ef to 818e0f7CompareMarch 25, 2022 16:00
@EnricoMi
EnricoMiforce-pushed the branch-datasourcev2-output-ordering branch 3 times, most recently from 7c67284 to 33623c2CompareApril 12, 2022 14:22
@EnricoMi

Copy link
Copy Markdown
ContributorAuthor

@sunchao@dongjoon-hyun looks like #35657 (20ffbf7) broke reusing partitioning and order provided by DS V2 in my tests, which worked before rebase. The query planner now introduces a shuffle and sort again.

Any suggestion how Spark can pick up the existing partitioning and order with the new partitioning design? Any plans for DS V2 to report ordering?

@EnricoMi

Copy link
Copy Markdown
ContributorAuthor

I have found the issue, option spark.sql.sources.v2.bucketing.enabled moved to default false, so I have to enable that to have order and partitioning being reused.

@EnricoMi

Copy link
Copy Markdown
ContributorAuthor

@sunchao#35657 says "have V2 data sources to report distribution and ordering to Spark on read path": How do V2 sources report their ordering?

@sunchao

Copy link
Copy Markdown
Member

@EnricoMi the ordering is not supported yet, but potentially can be done by adding another V2 RangePartitioning which coins the catalyst RangePartitioning class to report V2 ordering spec.

cc @cloud-fan@c21

@EnricoMi

Copy link
Copy Markdown
ContributorAuthor

So you are saying ordering is seen as being part of partitioning. This kind of makes sense.

Are you foreseeing that partitioning can transport in-partition order, rather than global order? For instance, some hash partitioning (having no global order) with some in-partition order as used by KeyValueGroupedDataset?

@sunchao

Copy link
Copy Markdown
Member

Yes I think it could be a useful addition to KeyGroupedPartitioning, for instance to skip the sort phase in SortMergeJoin. This property may not be preserved though, if there are multiple input partitions sharing the same partition values, as Spark needs to group them.

@cloud-fan

Copy link
Copy Markdown
Contributor

The internal SparkPlan.outputOrdering property is for data ordering within partitions. If a data source scan want to report a global ordering, it needs to report RangePartitioning as well as a data ordering within partitions using the same keys.

That said, I think a new API SupportsReportOrdering makes sense to report the data ordering within partitions.

@EnricoMi
EnricoMiforce-pushed the branch-datasourcev2-output-ordering branch from 36e2678 to 699c607CompareApril 19, 2022 14:11
@EnricoMi

Copy link
Copy Markdown
ContributorAuthor

@cloud-fan thanks for clarification, I have incorporated this distinction into the documentation of SupportsReportOrdering.

@EnricoMi

Copy link
Copy Markdown
ContributorAuthor

@cloud-fan who would be best to review this?

@HyukjinKwon

Copy link
Copy Markdown
Member

cc @aokolnychyi too FYI

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not correct since Spark can combine input partitions (see groupPartitions).

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Combining the partitions through groupPartitions does not preserve order (when concatenated), that is right. It could be preserved by merging the partitions, though.

The outputOrdering of the data source is as stated. Whoever calls into groupPartitions should consider that order is not preserved (depending on how the Seq[InputPartition] is used) if existing order is desired.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whoever calls into groupPartitions should consider ...

Yes, although groupPartitions is called by Spark right now so we should update accordingly in this PR too. Otherwise, after this PR the outputOrdering could be incorrect if grouping happen.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alright, when partition grouping happens and multiple partitions are grouped, ordering cannot be preserved.

I have modified outputOrdering not to return the ordering in that case. Making grouped partitions preserve order is out-of-scope of this PR.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm when partitions.length == 1 I think partition combining can still happen? partitions is of type Seq[Seq[InputPartition]] so even if its length = 1, the inner Seq[InputPartition] can still contain more than one elements.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right, I mis-interpreted if (partitions.length == 1) SinglePartition in def outputPartitioning, but partitions already incorporates groupedPartitions. Fixing that.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if logicalLink is the idiomatic way of processing a logical plan here (don't see it used much elsewhere) - normally we do in an optimizer rule like V2ScanPartitioning or V2Writes.

@cloud-fan@viirya do you see any issue with this?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not totally sure this is the correct approach. Could we follow the existing pattern and add an optimizer rule to populate this? we can re-use existing V2ScanPartitioning too (and change its name).

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome! Rules is where the magic happens...

Integrating this into V2ScanPartitioning makes this so much nicer, gets rid of the awful this.logicalLink.isDefined.

I have renamed V2ScanPartitioning to V2ScanPartitioningAndOrdering.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: spaces

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This may need to be updated since column "i" may not be in the "partitionKeys".

@EnricoMi
EnricoMiforce-pushed the branch-datasourcev2-output-ordering branch from 1b024e8 to f421607CompareMay 9, 2022 11:20
@EnricoMi

Copy link
Copy Markdown
ContributorAuthor

@sunchao I have pushed all my changes

@EnricoMi
EnricoMiforce-pushed the branch-datasourcev2-output-ordering branch from f421607 to 4ba19f7CompareMay 16, 2022 10:16
@EnricoMi

Copy link
Copy Markdown
ContributorAuthor

@sunchao@HyukjinKwon@aokolnychyi@cloud-fan I have addressed comments and rebased.

@sunchaosunchao left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry to get back so late @EnricoMi . Just got time to go through this PR again. Some more comments: mostly nits except one.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: indentation looks off here

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: space before Arrays

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: break this into multiple lines:

MyNamedReference(String part) {
this.parts = new String[] { part }; }

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

similarly for other places

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: indent

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not totally sure this is the correct approach. Could we follow the existing pattern and add an optimizer rule to populate this? we can re-use existing V2ScanPartitioning too (and change its name).

@EnricoMi
EnricoMiforce-pushed the branch-datasourcev2-output-ordering branch 3 times, most recently from 7c90fd1 to 2e1f5d9CompareJune 9, 2022 08:16
@EnricoMi

Copy link
Copy Markdown
ContributorAuthor

@sunchao@cloud-fan all comments addressed, all tests green

@EnricoMi
EnricoMiforce-pushed the branch-datasourcev2-output-ordering branch from 2e1f5d9 to 73c13deCompareJune 16, 2022 08:15

@sunchaosunchao left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Thanks, and sorry for the late response.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit nit: can we keep this one-line?

valscanRules=Seq[LogicalPlan=>LogicalPlan](partitioning, ordering)

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, done. Thanks for the review!

@EnricoMi
EnricoMiforce-pushed the branch-datasourcev2-output-ordering branch from 73c13de to e444a5dCompareJune 18, 2022 08:31
@sunchao

Copy link
Copy Markdown
Member

Merged to master, thanks!

@EnricoMi

Copy link
Copy Markdown
ContributorAuthor

Thanks @sunchao

@EnricoMi
EnricoMi deleted the branch-datasourcev2-output-ordering branch June 21, 2022 17:44
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@EnricoMi@AmplabJenkins@sunchao@cloud-fan@HyukjinKwon