-
Notifications
You must be signed in to change notification settings - Fork 928
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
NHibernate query plan for Linq Dml is not cached #2222
Comments
To demonstrate performance result I wrote a small test that updates same records with different values, Result Linq queries are 8-16 times slower execution, because of QueryPlanCache I think. When I look at the log of NHibernate batcher both linq and hql commands executed same time about 15-25 ms but overall elapsed times are to much different. I can use Hql Batch it just does the job as batch that I want but my team and I prefer Linq over Hql or QueryOver. One by One update is more slower than batching both linq and hql as expected. Windows 10 i7 2.88 16GB Ram Oracle 11g NH 5.2.6 Release Mode var accounts = ISession.Query<StmtAccountStat>().Where(x => x.FirstDelayDate == null).Take(500).Select(x => x.AccountNo).ToList();
var progress = (0, 0);
Random random = new Random();
Stopwatch watch = Stopwatch.StartNew();
for (int i = 0; i < 5; i++)
{
watch.Restart();
var batch = ISession.CreateQueryBatchDml();
foreach (var item in accounts)
{
DateTime date = DateTime.Now.AddDays(random.Next(30));
var query = ISession.CreateQuery($"update {typeof(StmtAccountStat)} set FirstDelayDate = :FirstDelayDate where AccountNo = :AccountNo");
query.SetParameter("FirstDelayDate", date);
query.SetParameter("AccountNo", item);
batch.Add(query);
}
batch.Execute();
Console.WriteLine("Hql Batch:" + watch.ElapsedMilliseconds);
Commit(ref progress);
watch.Restart();
foreach (var item in accounts)
{
DateTime date = DateTime.Now.AddDays(random.Next(30));
var query = ISession.CreateQuery($"update {typeof(StmtAccountStat)} set FirstDelayDate = :FirstDelayDate where AccountNo = :AccountNo");
query.SetParameter("FirstDelayDate", date);
query.SetParameter("AccountNo", item);
query.ExecuteUpdate();
}
Console.WriteLine("Hql One by One:" + watch.ElapsedMilliseconds);
Commit(ref progress);
watch.Restart();
foreach (var item in accounts)
{
DateTime date = DateTime.Now.AddDays(random.Next(30));
var query = ISession.Query<StmtAccountStat>().Where(x => x.AccountNo == item)
.UpdateBuilderBatch()
.Set(x => x.FirstDelayDate, date)
.CreateQuery();
batch.Add(query);
}
batch.Execute();
Console.WriteLine("Linq Batch:" + watch.ElapsedMilliseconds);
Commit(ref progress);
watch.Restart();
foreach (var item in accounts)
{
DateTime date = DateTime.Now.AddDays(random.Next(30));
var query = ISession.Query<StmtAccountStat>().Where(x => x.AccountNo == item)
.UpdateBuilder()
.Set(x => x.FirstDelayDate, date)
.Update();
}
Console.WriteLine("Linq One by One:" + watch.ElapsedMilliseconds);
Commit(ref progress);
}
watch.Restart();
ISession.Query<StmtAccountStat>()
.Where(x => accounts.Contains(x.AccountNo))
.Update(x => new StmtAccountStat() { FirstDelayDate = default(DateTime?) });
Console.WriteLine("Linq Batch Full Null:" + watch.ElapsedMilliseconds);
Commit(ref progress);
watch.Stop();
Console.ReadLine(); |
This comment has been minimized.
This comment has been minimized.
@bahusoid private bool IsPlanNotCacheable(IQueryExpression queryExpression)
{
// 6.0 TODO: add IsPlanCacheable to IQueryExpression interface
return queryExpression is NhLinqExpression linqExpression && !true;
} Cached Linq NonCached Linq |
The query plan cache is never hit for linq DML queries.
NHLinqExpression.cs
p2 is Entity Class we should ignore in ExpressionParameterVisitor.cs VisitConstant
p5 is the property name that we want to update should be ignored
DmlExpressionRewriter.cs ConvertAssignmentsToDictionaryExpression method below code adds extra 2 parameter p3=1, p4=1 should be ignored
The text was updated successfully, but these errors were encountered: