Closed (won't fix)
Project:
Drupal core
Version:
8.7.x-dev
Component:
entity system
Priority:
Normal
Category:
Task
Assigned:
Unassigned
Reporter:
Created:
19 Dec 2016 at 14:20 UTC
Updated:
9 Feb 2019 at 14:32 UTC
Jump to comment: Most recent, Most recent file
Comments
Comment #2
hchonovA proof of concept patch.
Comment #4
hchonovOups..
Comment #5
hchonovAdding the changed key to the entity annotation.
Comment #7
hchonovComment #9
hchonovIt looks like adding dynamically the content_translation_changed field to the entity metadata keys in content_translation_entity_type_alter is causing problems on existing sites when rebuilding the cache and going into some infinite loops... So I am removing it for now.
Comment #11
hchonovComment #12
hchonovActually entity queries are complex and expensive so another option would be to introduce a new system table: entity_changed_tracking and a hook_entity_insert/update and upsert the changed time in the table if saving the default revision, then query this table instead of building an entity query.
Any thoughts on this?
Comment #13
amateescu commentedSince
\Drupal\Core\Entity\EntityChangedTraithard-codes the field name to 'changed', I think we can get away with hard-coding it as well in the entity query for now, and open a separate feature request issue to make the changed field name configurable, which ultimately would look like what we did in #2248983: Define the revision metadata base fields in the entity annotation in order for the storage to create them only in the revision table.@hchonov mentioned in IRC that someone could implement
EntityChangedInterfacewithout usingEntityChangedTrait, but that's an edge case IMO, for which we can keep the currentloadUnchanged()code as a fallback when an entity type doesn't have a 'changed' field.Comment #14
amateescu commentedRe #12: That would mean another custom table that alternative storage engines would have to implement, so it seems a bit of overkill for bypassing a simple entity query :)
Comment #15
hchonovWell we could probably use the key value store instead of creating a new table? So what do you think is better - entity query with hardcoded changed field name vs hook_entity_insert/update + key value storage?
Comment #16
hchonovWhat I was proposing is something like this by using the key value store for entity changed tracking. If you do not like the idea or think it is not worth the optimization then I would do an entity query instead. The current solution does not require any update hooks as there is a fallback in the EntityChangedConstraintValidator to load the unchanged entity if the key value store does not contain the changed time for the given entity.
Comment #17
hchonovOups .. a small mistake only using id as a name, but I had to use entity_type_id + entity id.
Comment #20
amateescu commentedMy personal opinion/preference would be entity query with hardcoded changed field name + fallback to load the unchanged entity.
The downside of the key value approach is that we need to track that an entity throughout its entire lifetime (create, update, delete) and then it's not really a performance optimization anymore.
Comment #23
hchonov@amateescu++
After the changes, that we've made in #2837022: Concurrently editing two translations of a node may result in data loss for non-translatable fields now I think as well that tracking the entity throughout its lifetime will be complex, because we would need to track each translation.
In the new patch I check if the entity has a changed field and if so perform an entity query, otherwise fallback to loading the unchanged entity from the storage. An interdiff doesn't really make sense, as the validator has changed its check to individually check each translation.
Comment #25
hchonovThe other changes introducing the entity changed tracking should be removed as well.
Comment #26
hchonovIf the entity type isn't translatable we should not add the language code to the entity query condition, as otherwise an exception will be thrown for a non-existent column "langcode":
.
Comment #29
hchonovI've forgot to narrow down the query based on the entity ID :).
But there is some problem with the entity queries when querying the same field in an OR condition group and specifying the langcode.
The failing patch uses a query like the following one:
which unfortunately is compiled to SQL where the language code is not part of each condition for the changed timestamp, but is used for the INNER JOIN:
The passing patch uses a query which looks like this:
which compiles to SQL where the language code is part of each condition for the changed timestamp:
Comment #30
hchonovI was able to move the comparison of the entity ID out of each condition for the changed timestamp, which results in the following SQL and should have better performance:
Comment #35
kfritscheI'm not an mysql expert but somehow this query is slow on our side.
We have 8 languages and around 4000 entities (16.000 rows in the table - so not all is translated to all languages yet)
The query build by entity API is:
Running this query takes 1 minute.
Using explain it doesn't seem to be a missing index problem or similar, but sitll here the output of explain.
Loading the full entity is better in our case than this query...
Comment #36
amateescu commentedSince #2753675: loadUnchanged should use the persistent cache to load the unchanged entity if possible instead of invalidating it,
loadUnchanged()is a very simple "persistent cache get" in most cases, and no entity query will ever be more performant than that.I think we should close this issue as won't fix. @hchonov, do you agree?
Comment #37
hchonov@amateescu, yes, you are right - we cannot improve this further.