Improve performance and API consistency by introducing node_delete_multiple(). The use case in core is the admin/content/node page. Additional use cases are Views Bulk Operations, migration scripts, and devel_generate.
If you are deleting 50 nodes, this patch replaces 200 DELETE queries with 4 DELETE queries. It also saves 50 calls to node_access() which can lead to 100 SELECT queries if you are using a node access module. And there is more to be gained if do multiple for search_wipe() and term delete, and so on.
At the same time, I've modernized node_delete a bit. I removed its internal access control as thats already done by the menu system. API functions shouldn't have access control. Similarly I moved the watchdog() and drupal_set_message() calls to the submit handlers which keeps the node_delete cleaner.
Comment | File | Size | Author |
---|---|---|---|
#23 | ndm.patch | 5.65 KB | moshe weitzman |
#21 | ndm.patch | 5.2 KB | moshe weitzman |
#19 | ndm.patch | 5.21 KB | moshe weitzman |
#15 | nmd.patch | 5.04 KB | moshe weitzman |
#13 | nmd.patch | 5.48 KB | moshe weitzman |
Comments
Comment #2
catchVery nice.
Looks like the node_load() needs to be moved before the deletes are run (and could presumably be node_load_multiple if so?). Also some debug left in the patch.
Comment #3
moshe weitzman CreditAttribution: moshe weitzman commentedDoh - thats why the node_load() was failing. I changed to node_load_multiple() and moved out of the loop. That saved another 49 queries. And I forgot that we saved 98 queries due to performing one cache_clear_all() instead of fifty. By my count, we are at about 445 saved queries.
Comment #4
moshe weitzman CreditAttribution: moshe weitzman commentedPreserve same drupal_set_message() so tests are happy.
Comment #5
catchneeds @param for $nids. Looks like node_delete() is missing it as well.
Apart from that and waiting on the test bot, this looks great.
Comment #6
moshe weitzman CreditAttribution: moshe weitzman commentedWith those params documented.
Comment #7
mikeryanI'm concerned about node relationships (whether through CCK related node fields, or module-specific relationships). What if a delete hook tries to reference a related node which was wiped out in the db_delete('node')? The answer, I believe, is that upward compatibility is not a goal and module maintainers will need to be sure their delete hooks gracefully deal with the situation, but at least we need to remember to document the change in behavior.
Another thing to document is that node_delete() will no longer do a drupal_set_message() - any module calling node_delete() and expecting a message to the user will need to roll its own.
node_load() here (unless the behavior is changed in D7) caches the nodes that are about to be deleted, which consumes gobs of memory when doing mass deletions. See #287063: node_delete "leaks memory" due to deleted nodes cached. Also note the suggestion there about reordering the deletion and the hook calls.
Thanks.
Comment #8
moshe weitzman CreditAttribution: moshe weitzman commentedMike - I think the referenced thing is a non-issue. nodeapi('delete') is passing in a full $node object that was made before the delete happenned on the node tables. Modules can take whatever action they deem necessary - they have all the info they need. This also addresses your other concern about order of operations for the delete queries.
Yes, I will document the dsm() and watchdog change on the module update page.
I added a $write_cache param to node_load_multiple which defaults to true but is set to false by node_delete_multiple. This should address most of the memory concerns.
Comment #9
catchWhy not just use the $reset parameter? That'll disable the static as well, saves the extra param, and it's not that likely the nodes will already have been loaded on the same request that they get deleted.
Comment #10
moshe weitzman CreditAttribution: moshe weitzman commentedIf I read it correctly, $reset just wipes the cache at the beginning of the function - that doesn't really help avoid the saving at the end. We want to avoid populating the global $node_cache since thats what causes memory bloat.
Seems like we should convert $node_cache to a drupal_static() and then the caller can reset cache before or after the call to node_delete_multiple(). Thats quite a bit cleaner. Patch attached.
Comment #11
catchHmm, good point. That's much nicer anyway though. Looks ready to me, but didn't run all tests on it and the bot is still catching up.
Comment #13
moshe weitzman CreditAttribution: moshe weitzman commentedI put back the $reset param since I think it is nice for the function to perform the reset instead of the caller. Better encapsulation. The change to drupal_static stays in place, and it does allow the callers to clear the cache which is important. This patch is back to its simple self.
Comment #14
BerdirPlaying DBTNG Coding Style watchdog again, the following lines aren't correctly intented..
condition and execute should be intented two more spaces.
Comment #15
moshe weitzman CreditAttribution: moshe weitzman commentedfixed indentation.
Comment #16
moshe weitzman CreditAttribution: moshe weitzman commenteddoes the bot really complete the test suite in 3 minutes! I need some of that. se http://testing.drupal.org/pifr/file/1/nmd_0.patch
Comment #17
catchTests pass, code looks good, existing API still works the same, we should add a short note to update docs after commit. RTBC.
Comment #19
moshe weitzman CreditAttribution: moshe weitzman commentedreroll. back to rtbc.
Comment #20
sunLooks good.
Blank lines should be blank (white-space here).
Empty line here.
Blank PHPDoc lines should be blank (trailing white-space here and also node_delete_multiple()).
What bugs me a bit is that there is no error handling in here. However, that's out of the scope for this issue.
Comment #21
moshe weitzman CreditAttribution: moshe weitzman commentedFixed whitespace.
Comment #22
sunYou're sure that this was the right patch? I'm not sure what changed in there, but the issues of #20 are still contained.
Comment #23
moshe weitzman CreditAttribution: moshe weitzman commentedRetrying.
Comment #24
sunNice!
Comment #25
webchickVery nice!
I also like that those watchdog messages are moved to the confirm form rather than within the API function. Icky.
Committed to HEAD. Please note the addition of this function on the 6.x -> 7.x upgrades page.
Comment #26
moshe weitzman CreditAttribution: moshe weitzman commentedAdded upgrade docs.