-
Notifications
You must be signed in to change notification settings - Fork 3.2k
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
ExecuteUpdate on Oracle and sub-optimal query #30742
Comments
@anoordover I'm familiar with MERGE from SQL Server and PostgreSQL, and as far as I know it isn't typically used for the same things that UPDATE is used; while UPDATE can be used to bulk-update many rows in a single table, MERGE is typically used to merge data from one table (or from the client) into another table. Can you please provide more context on exactly what you're doing, showing the (apparently inferior) UPDATE and (apparently superior) MERGE, as well as the plans for these?
I'd say there's very little chance that ExecuteUpdate will be changed to use MERGE under the covers (although we're not the ones maintaining the Oracle driver). ExecuteUpdate really models the SQL UPDATE statement, MERGE is a different statement with its own syntax etc. |
I will continue my investigation on Monday. But for now: |
When my previous comment is correct I think:
When writing merge statements is difficult for a team they could use Open AI to rewrite an UPDATE statement to a MERGE statement ;) |
@anoordover I highly recommend bringing a concrete sample here with an actual UPDATE and MERGE which are equivalent, but where the MERGE is apparently more efficient - this is a bit too abstract to reason about without seeing actual SQL statements. If there's indeed a category of cases where a SQL UPDATE can be transformed to a MERGE and that MERGE works more efficiently, then it may indeed make sense for ExecuteUpdate to to do that. If this is true for other databases which support MERGE (SQL Server, PostgreSQL), then this is something we could consider doing in EF Core itself. Otherwise, the Oracle team could add this optimization to their own provider. But again, we need to see actual statements and plans. |
Please let me know if you need more information In the plan for the MERGE-statement you see the HASH JOIN that I mentioned before. Thinking about these differences triggered me to think about what I would expect when executing an executeupdate statement that uses a source table for updating a field in the target table. My question is: Is it the expected behavior that also the rows in the target table get updated when there is no row being found in the source table or should you be forced to define a where clause on the target table so that only rows will be selected having a matching row in the source table? |
Adding a where clause on the target table in the UPDATE statement gives me the plan added below.
|
@anoordover OK. I'd be surprised if Oracle provided no way to do such a simple UPDATE efficiently, forcing users to resort to MERGE syntax instead. Specifically for your first UPDATE above, that contains a correlated subquery, i.e. it references d.INDIVIDUALCLAIM_REFERENCE from the outer table, meaning that the subquery needs to run for each row in the outer table (INDIVIDUALPAYMENT). This is indeed always bad for perf, also for non-UPDATE queries and on other databases. Most databases allow expressing JOINs instead - just like you can do in regular queries; that does the same thing but much more efficiently. I'm no Oracle expert, so I'm not sure what's possible here. Note that in any case, #4526 may introduce a way to express MERGE - although that issue still requires lots of careful thinking and design. If it really makes sense in the Oracle context to implement some types of ExecuteUpdate via MERGE rather than UPDATE, then the maintainers of the Oracle provider may be able to add that ability to their provider specifically. |
As a side note... Did you notice the temp storage usage in the last plan and the MERGE plan? Second side note: Oracle says that they don't support executeupdate yet (but they don't throw an exception) |
@anoordover it seems we're discussing several different things (specifically in oracle/dotnet-db-samples#270). AFAIK basic ExecuteUpdate does work with Oracle. You seem to have encountered a specific bug with the invalid SQL - that's likely to be a problem on the Oracle side (though not sure), I'd advise tracking that separately from the other ExecuteUpdate-related problems. |
@roji It seems you are right. Simple executeUpdates work but if you have a complex where-query, Oracle actually generates a |
@michiproep thanks for confirming - it's probably a good idea to make Oracle aware of this. |
In oracle you have two ways to update multiple rows from one table with data from another table:
Both these statement yield to a different execution plan where the second one is better when updating and querying a lot of rows.
Before EF Core version 7 you could only do these kind of update using raw SQL.
From EF Core version 7 you can also use ExecuteUpdate to do these kinds of updates.
My opinion is that when we choose raw SQL because of this issue we need to measure if this issue is still viable and change our code to use ExecuteUpdate when this situation isn't viable anymore (Oracle DB optimizer, EF Core or the Oracle EF Core implementation might change).
Or we might accept the performance impact and use ExecuteUpdate so me en my colleagues only need to have knowledge about EF Core.
What would you do:
The text was updated successfully, but these errors were encountered: