Skip to content
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

Add infrastructure for too many Includes warning. #20140

Closed
wants to merge 1 commit into from

Conversation

ajcvickers
Copy link
Member

Part of #19933

@ajcvickers
Copy link
Member Author

@smitpatel My part of #19933. Warning is not wired up yet--need you for that.

@smitpatel
Copy link
Member

What is our cut-off to generate warning?

@ajcvickers
Copy link
Member Author

@smitpatel I'll just let you take over this PR in whatever way you want, since I can't get approval to merge until the complete change is done anyway.

@AndriySvyryd
Copy link
Member

@smitpatel If the query has two or more collection includes or collection nav expansions then we should generate the warning

/// <param name="diagnostics"> The diagnostics logger to use. </param>
/// <param name="expressionPrinter"> Used to create a human-readable representation of the expression tree. </param>
/// <param name="queryExpression"> The query expression tree. </param>
public static void TooManyIncludesWarning(
Copy link
Member

Choose a reason for hiding this comment

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

The place we know that there too many includes in relational, we don't have actual expression tree.

Copy link
Member Author

Choose a reason for hiding this comment

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

@smitpatel I can update it to take whatever you have available.

Copy link
Member

Choose a reason for hiding this comment

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

Let's discuss in triage today.

@smitpatel
Copy link
Member

I looked at this further, the place where we accurately know that there is multiple collection projection, we only have SelectExpression. Further, in order to print SelectExpression in most readable format, we need sql generator which we don't have. Any other place to identify this requires a public surface on places where we don't want to add public surface. (even if we add in patch, it would be throw away work).

At this point, warning seems pretty low value as if query (with or without multiple collection include), either it works just fine or perf is pretty bad and customers would know.

@ajcvickers
Copy link
Member Author

@smitpatel Can we get any type of string from the SelectExpression? If so, can you post examples of what it looks like?

@smitpatel
Copy link
Member

Can strip out shaper if needed

(ShapedQueryExpression: 
    QueryExpression: 
        (Projection Mapping:
        SELECT ((c.CustomerID)), ((c.Address)), ((c.City)), ((c.CompanyName)), ((c.ContactName)), ((c.ContactTitle)), ((c.Country)), ((c.Fax)), ((c.Phone)), ((c.PostalCode)), ((c.Region)), ((t.OrderID)), ((t.CustomerID)), ((t.EmployeeID)), ((t.OrderDate)), ((t.OrderID0)), ((t.ProductID)), ((t.Discount)), ((t.Quantity)), ((t.UnitPrice))
        FROM (Customers AS c)
        (LEFT JOIN (Projection Mapping:
        (
            SELECT ((o.OrderID)), ((o.CustomerID)), ((o.EmployeeID)), ((o.OrderDate)), ((o0.OrderID) AS OrderID0), ((o0.ProductID)), ((o0.Discount)), ((o0.Quantity)), ((o0.UnitPrice))
            FROM (Orders AS o)
            (LEFT JOIN (Order Details AS o0) ON ((o.OrderID) == (o0.OrderID)))
        ) AS t) ON ((c.CustomerID) == (t.CustomerID)))
        ORDER BY ((c.CustomerID) ASC), ((t.OrderID) ASC), ((t.OrderID0) ASC), ((t.ProductID) ASC))
    ShaperExpression: (IncludeExpression(
            (EntityShaperExpression: 
                EntityType: Customer
                ValueBufferExpression: 
                    (ProjectionBindingExpression: CustomerID:0,
                        Address:1,
                        City:2,
                        CompanyName:3,
                        ContactName:4,
                        ContactTitle:5,
                        Country:6,
                        Fax:7,
                        Phone:8,
                        PostalCode:9,
                        Region:10,
                    )
                IsNullable: False
            ), 
            (RelationalCollectionShaper:
                CollectionId: 0
                ParentIdentifier:new object[]{ (ProjectionBindingExpression: 0) }
                OuterIdentifier:new object[]{ (ProjectionBindingExpression: 0) }
                SelfIdentifier:new object[]{ (object)(ProjectionBindingExpression: 11) }
                InnerShaper:(IncludeExpression(
                    (EntityShaperExpression: 
                        EntityType: Order
                        ValueBufferExpression: 
                            (ProjectionBindingExpression: OrderID:11,
                                CustomerID:12,
                                EmployeeID:13,
                                OrderDate:14,
                            )
                        IsNullable: True
                    ), 
                    (RelationalCollectionShaper:
                        CollectionId: 1
                        ParentIdentifier:new object[]{ (object)(ProjectionBindingExpression: 11) }
                        OuterIdentifier:new object[]{ (object)(ProjectionBindingExpression: 11) }
                        SelfIdentifier:new object[]
                        { 
                            (object)(ProjectionBindingExpression: 15), 
                            (object)(ProjectionBindingExpression: 16) 
                        }
                        InnerShaper:(EntityShaperExpression: 
                            EntityType: OrderDetail
                            ValueBufferExpression: 
                                (ProjectionBindingExpression: OrderID:15,
                                    ProductID:16,
                                    Discount:17,
                                    Quantity:18,
                                    UnitPrice:19,
                                )
                            IsNullable: True
                        )
                        Navigation: OrderDetails
                    ), OrderDetails)
                )
                Navigation: Orders
            ), Orders)
        )
)

@ajcvickers
Copy link
Member Author

@smitpatel Thanks. Let's discuss again in triage. :-)

@AndriySvyryd
Copy link
Member

This still has value. If one needs to identify the query that triggers the warning they can just set it to throw.

@smitpatel
Copy link
Member

This still has value.

You mean warning or exception message? Because in today's triage while discussing, people said, if we cannot give good indication of which query then it is not useful.

@AndriySvyryd
Copy link
Member

You mean warning or exception message?

It's one and the same, depends on user configuration.

Because in today's triage while discussing, people said, if we cannot give good indication of which query then it is not useful.

If it throws then it's clear

@@ -250,6 +250,10 @@
<value>Possible unintended use of a potentially throwing aggregate method (Min, Max, Average) in a subquery. Client evaluation will be used and operator will throw if no data exists. Changing the subquery result type to a nullable type will allow full translation.</value>
<comment>Warning RelationalEventId.QueryPossibleExceptionWithAggregateOperatorWarning</comment>
</data>
<data name="LogTooManyIncludesWarning" xml:space="preserve">
<value>The query '{query}' uses 'Include' for more than one collection navigation property. Including multiple collections can result in slow query performance. See ... for more information.</value>
Copy link
Member

@AndriySvyryd AndriySvyryd Mar 7, 2020

Choose a reason for hiding this comment

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

Don't forget to replace the ...

And add "To identify the query that's triggering this warning call .ConfigureWarnings(w => w.Throw(RelationalEventId.LogTooManyIncludesWarning))"

@ajcvickers
Copy link
Member Author

@smitpatel What I intended to say in triage was, "if we cannot give any indication of which query then it is not useful." :trollface:

@ajcvickers
Copy link
Member Author

Blocked for now until we have the new code in place.

@ajcvickers
Copy link
Member Author

@smitpatel Is this PR now obsolete?

@AndriySvyryd
Copy link
Member

How else will the users find out that they need to call the new API?

@ajcvickers
Copy link
Member Author

@AndriySvyryd I meant specifically this PR, not the concept of having a warning.

@smitpatel
Copy link
Member

So should I put this thing to master and generate warning when not split query and more than one collection is being projected/included?

@ajcvickers
Copy link
Member Author

@smitpatel Yes. :-D

@smitpatel
Copy link
Member

Superseded by #21419

@smitpatel smitpatel closed this Jun 26, 2020
@smitpatel smitpatel deleted the WarningMyToesByTheRyzen0303 branch June 26, 2020 00:10
Sign up for free to 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.

3 participants