-
Notifications
You must be signed in to change notification settings - Fork 3.6k
HHH-15045 avoid dirty-flush for OneToOne type #5061
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
ce7f77d
to
c9e8573
Compare
* We don't need to dirty check one-to-one because of how | ||
* assemble/disassemble is implemented and because a one-to-one | ||
* association is never dirty | ||
*/ |
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.
The reverted original comment says all
60b538a
to
58aad75
Compare
return resolve( session.getContextEntityIdentifier( owner ), session, owner ); | ||
} | ||
return null; | ||
} |
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.
@dreab8 , I saw there were quite some back and forth (see https://hibernate.atlassian.net/browse/HHH-15044); but I think after we revert back the dirty flush related code changes, the above code seems to become necessary again. I am not sure about this, though. Feel free to take over and work on top of my PR or even close it.
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.
@NathanQingyangXu this is the discussion that led to the revert https://hibernate.zulipchat.com/#narrow/stream/132094-hibernate-orm-dev/topic/PR.204221
290f773
to
5582d1e
Compare
Please do not change the behavior here. The one-to-one is dirty whenever it is associated becomes associated because it needs to track when it is associated. The association does not change the way the object is stored in the database, but does change how it is stored in the cache. If you revert this code you you will cause a cache miss and a database hit whenever |
But it seems your testing case was not broken when it was reverted back. Am
I missing something?
…On Tue., May 17, 2022, 3:41 p.m. deAtog, ***@***.***> wrote:
Please do not change the behavior here. The one-to-one is dirty whenever
it is associated becomes associated because it needs to track when it is
associated. The association does not change the way the object is stored in
the database, but does change how it is stored in the cache. If you revert
this code you you will cause a cache miss and a database hit whenever
resolve is called. This negatively impacts performance and is the reason
it was changed.
—
Reply to this email directly, view it on GitHub
<#5061 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AB6UYAV4HD7B3Z6LHWONFUDVKPY6BANCNFSM5WDBQLGQ>
.
You are receiving this because you authored the thread.Message ID:
***@***.***>
|
Looking back at those tests, they do not really seem to test the dirty aspect of the OneToOneType with respect to caching. I think you should implement some other tests to ensure that the behavior is as expected before and after your changes. Before my changes, The changes in these implementations necessitate a dirty check because adding an associated object to an existing one when using a foreign key relationship should update the cache of the existing object, but not the database. |
I am not sure we should change dirtiness to suit the cache purpose. To my feelings, the dirtiness should be retained to db sync up issue only. We should strive to achieve both goals (1. no touch on dirtiness or dirtiness should always be false; 2. make second-level cache working). Seems your previous code changes in |
As is right now, if it's marked dirty and there are no database changes the cache will be updated and the database will not. Unfortunately, there is not a way to determine whether or not it is dirty with respect to the cache or respect to the database. If you change the behavior here, performance will undoubtedly suffer whenever you have a local cache and a remote database. The purpose of my changes were to improve the cache performance while having a very minimal impact otherwise. Prior to my changes, whenever assemble was called with I don't fault you trying to optimize the little bit of overhead incurred here, but I do not think you are going about it the right way. Also, I think there are far bigger fish out there than this. |
This is a big fish if you inspect https://hibernate.atlassian.net/browse/HHH-15045. Obviously a regression issue happens and we should fix it. From my understanding, you reuse the well-defined 'dirtiness' methods to go about your cache implementation performance optimization (not for feature for without these changes you testing case is still fine), but it might break a lot for many users are expecting the canonical dirtiness mechanism to go about their processing. |
I reviewed the above regression. I think we both agree that some mechanism is need to differentiate the whether the one-to-one is dirty from a caching perspective vs a database perspective. Right now the automatic versioning seems to treat the dirtiness of the one-to-one as the only condition required to increment the version, which ultimately is what causes the database update to occur. Without versioning, there isn't an issue. None of the existing tests cover this scenario, hence the regression. |
Thanks. Makes sense.
…On Fri., May 20, 2022, 10:55 a.m. deAtog, ***@***.***> wrote:
I reviewed the above regression. I think we both agree that some mechanism
is need to differentiate the whether the one-to-one is dirty from a caching
perspective vs a database perspective. Right now the automatic versioning
seems to treat the dirtiness of the one-to-one as the only condition
required to increment the version, which ultimately is what causes the
database update to occur. Without versioning, there isn't an issue. None of
the existing tests cover this scenario, hence the regression.
—
Reply to this email directly, view it on GitHub
<#5061 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AB6UYAXT4XI3IM4NJ2DB4KDVK6RVTANCNFSM5WDBQLGQ>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
I debugged your testing case and set breakpoints into I think we have good reason to revert back your code changes involving dirtiness checking, though yours in assemble() and disassemble() are valid. I will consider adding a more compelling testing case and then I will label this PR as ready. |
I found a good testing case and updated. When the OneToOne owner side update its association, the Obviously the bug was because of misunderstanding of the dirtiness related methods in |
As I stated previously, the test cases I added during my initial PR did not test the dirtiness of the OneToOneType. I do not believe the changes you've made to
Prior to adding implementations for As I stated before, I think more tests are needed here. The one test you've added demonstrates a problem, but you have not included enough tests to verify you are not breaking caching of the OneToOneType with |
I think we'd better limit the scope of this PR to dirtiness exclusively, not caching. If you were interested, maybe you can take over. But we'd better separate two issues: 1) cache; 2) dirtiness. The code I added was from @dreab8 to cover the later testing case after yours (with |
I am confused for I did inspect your commit history carefully. Especially, I found prior to step 3, your testing case has succeeded already. Did you mean your existing testing cases uncommitted? I agree we should cover more testing cases, but given the current testing coverage status, I could only go thus far. |
We need this PR desperately, which reverts the change made to @OnetoOne dirty check in PR #3590. PR #3590 has been blocking our upgrading path from 5.4.x for months. It's nice to see caching improvement attempt, but we should ensure correctness first, which in this case is dirty check. There are other people like me eagerly waiting for it reverted back to old behavior. |
@NathanQingyangXu Unfortunately this change seems to introduce a regression, I ported a test we have in 5.x but not in 6 and it fails. |
After some discussion, we came to the conclusion that the fix which was introduced with #3590 for HHH-14216 is invalid, and we will revert it based on what this PR here does. The proper performance improvement for one-to-one associations is IMO to introduce "tombstone" cache entries for the entity type of the one-to-one association, which serve as null markers. This way, we would hit the cache instead of the database and see the tombstone cache entry, which we interpret as null. |
OMG "tombstone" I love it. |
Really appreciate it! I can't wait to upgrade to the latest version of hibernate in our projects. |
superseded by #5330 |
But I am not sure your reusing "dirtiness" (which is for db purpose) for
cache implementation detail is a good idea. It might hurt in the other way.
Also, I don't think reverting dirtiness back would hurt performance, on the
contrary, it might save a lot in other scenarios. I will investigate
further to demonstrate we can achieve both goals at the same time.
…On Thu., May 19, 2022, 11:07 a.m. deAtog, ***@***.***> wrote:
As is right now, if it's marked dirty and there are no database changes
the cache will be updated and the database will not. Unfortunately, there
is not a way to determine whether or not it is dirty with respect to the
cache or respect to the database. If you change the behavior here,
performance will undoubtedly suffer whenever you have a local cache and a
remote database. The purpose of my changes were to improve the cache
performance while having a very minimal impact otherwise. Prior to my
changes, whenever assemble was called with fetch="join" and a related
object did not exist in the cache, a database query was performed to verify
that there was indeed no related object. Given that the purpose of a
one-to-one is to store extra data that is typically sparsely populated,
these queries were very expensive to execute.
I don't fault you trying to optimize the little bit of overhead incurred
here, but I do not think you are going about it the right way. Also, I
think there are far bigger fish out there than this.
—
Reply to this email directly, view it on GitHub
<#5061 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AB6UYAWB5FOXUJXHHQMEFTLVKZKKZANCNFSM5WDBQLGQ>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
Maybe, and maybe not. I dug into the code for versioning and right now all one-to-one relationships are versioned. For a one-to-one relationship, there are the following scenarios to consider.
In the first case, the relationship from the parent to the child should not be versioned as the child is dependent upon the parent. In the reverse mapping from the child to the parent, the Id of the child should be versioned, but the one-to-one should not. In the second case, the relationship from the parent to the child should not be versioned as the child is once again dependent upon the parent. In the reverse mapping from the child to the parent the one-to-one should be versioned as the parent Id is stored in a separate column. In the third case, the relationship from the parent to the child should be versioned as the parent stores the Id of the child in a separate column. In the reverse mapping from the child to the parent, the one-to-one should not be versioned as the child contains no information about the parent. If the versionability of the one-to-one is corrected then the version will not be incremented and no database update will occur. It is therefore my opinion that this issue can be solved by addressing the versionability of the one-to-one. |
https://hibernate.atlassian.net/browse/HHH-15045
For the following simple OneToOne case:
Internally the 'user' field in
Profile
would be treated as@ManyToOne
, not@OneToOne
. themappedBy
side is treated as the only@OneToOne
type. For this reason, OneToOneType is always clean, never dirty.This is a regression issue after #3590 (for https://hibernate.atlassian.net/browse/HHH-14216). After reverting back the changes in
OneToOneType
class, the testing case is still fine in that PR.