-
Notifications
You must be signed in to change notification settings - Fork 933
Rewrite string.Contains/string.StartsWith/string.EndsWith to SqlMethods.Like so DB can reuse query plan #2396
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
This reverts commit d1ec908.
return Expression.Call( | ||
Like, | ||
expression.Object, | ||
Concat(expression.Arguments[0], Expression.Constant("%")) |
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 escaping works for such queries? I mean do we really properly support queries like Where(x => x.Name.StartsWith("%"))
?
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.
It is not supported at the moment.
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.
Related: #484, #488, NH-3726, 9be7d06.
The StartsWith
, EndsWith
, Contains
cases were a comment "side note" in NH-3726 and #484. The main point of NH-3726 was only about SqlMethod.Like
. #484 and #488 were PR doing this, and it seems the corresponding fix has ended up committed directly as 9be7d06.
Anyway we lack an opened issue for supporting escaping with these methods, and as said in #484, it will be a possible breaking change.
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.
No, we have @fredericDelaporte. #877.
I have a concern about this change here:
What are your thoughts about it? |
To check about parameter sniffing, you must try with different parameters values, with an index on the "liked" column, with some parameters values starting with |
Thanks for the link. I played with different parameters by clearing query cache each time and realized that also DBCC FREEPROCCACHE;
exec sp_executesql N'SELECT l.Value FROM Location l left join Location l2 on l.Id = l2.Id WHERE l.Value LIKE @id2 AND l2.Id <> @id2', N'@id2 NVARCHAR(5)', @id2='%1%'
DBCC FREEPROCCACHE;
exec sp_executesql N'SELECT l.Value FROM Location l left join Location l2 on l.Id = l2.Id WHERE l.Value LIKE @id2 AND l2.Id <> @id2', N'@id2 NVARCHAR(5)', @id2='1%'
DBCC FREEPROCCACHE;
exec sp_executesql N'SELECT l.Value FROM Location l left join Location l2 on l.Id = l2.Id WHERE l.Value LIKE @id2 AND l2.Id <> @id2', N'@id2 NVARCHAR(5)', @id2='%1' in the above example all three statements have a different query plan. Now I don't quite understand the following statement from #725:
From my current understanding, having one plan for all three statements won't increase the performance, infact it may only reduce it when the database engine would produce different query plans. Currently, we don't have any reported issues regarding producing too many query plans that would cause a performance drop, so maybe we shouldn't reuse the same query plan even for |
Well, recomputing a query plan is slower than using an existing one, if the existing one is suitable. But this gain is in my view marginal against the gain of using a suitable plan. |
Correct, I forgot about that. So these are the current differences: Current master: This PR: For me the benefit of having a different query plan for each method outweighs the benefits from this PR, as a bad query plan may cause the query to run multiple times slower. In order to support both scenarios, I made an alternative PR #2411, that adds the ability to configure the pre-transformation by the user. |
Closing in favor of #2411 |
This discussion seems to be the problem I am having :( We are using an old version of nHibernate where it generates StartsWith as: While on SQL server it may seem that both @p+'%' and the one that include '%' in parameter generating the same execution plan, SQL server generates a plan per call ! |
Fixes #725