Order synchronization performance issues in large stores #40757
Replies: 5 comments 2 replies
-
Thanks Néstor for starting this discussion. I wonder if there's any need or benefit to knowing the exact number of orders to be synchronized -- is it maybe sufficient to say something like "more than 10,000 orders are waiting to be synchronized"? We could still use an incremental approach to the counting like you're suggesting but could be done much sooner. In addition, I was wondering that maybe that counting process could live in a scheduled action that simply updates the cached value. Then the query wouldn't really depend on someone needing a value right now. We could update it every five minutes, for example. Not sure how beneficial that would actually be though? |
Beta Was this translation helpful? Give feedback.
-
Beta Was this translation helpful? Give feedback.
-
my second query can be rewritten from
to the uglier
This went from 5.4s to 3s on our live data. Still not great, but a reasonable improvement. Not sure if @OllieJones can help with those queries? (sorry for cold-calling!) |
Beta Was this translation helpful? Give feedback.
-
Which DBMS? Which version? Both these query patterns ( Depending on the version of DBMS software, the query planner probably comes up with identical or very similar ways to satisfy them. It's really hard to know what the query planner cooked up without seeing the output of EXPLAIN, or better, ANALYZE. (ANALYZE actually performs the query), The difference between 3s and 5.4s can often be explained by the first attempt pulling a whole mess of data into the buffer pool, and the second attempt using that same buffered data. I wish I had a more definitive answer. Bulk data ops can be slow. |
Beta Was this translation helpful? Give feedback.
-
Thanks Ollie. in our case it's MariaDB 10.5.20. We've finally completed the migration, so hopefully it won't be an issue for us going forwards, however, I'm slightly worried about the problem of this discussion as described here #40757 (comment) and more specifically the following which we might come across later
|
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
The problem
There's an open issue concerning the performance the database query to count orders pending synchronization (#40506): on sites with a large number of orders the query takes so long that WordPress hangs.
I've tested with a sandbox of about 9 million orders in its database, and indeed trying to run the query showcased in the issue causes the database connection to timeout after one minute.
Here's an improved version of the same query suggested by @vedanshujain:
This query runs in 45 seconds in the aforementioned sandbox, which is still too much.
It's not mentioned in the issue, but the queries for retrieving the ids of the orders requiring synchronization can potentially take too long too:
This post only discusses the query that count the orders, with the understanding that the queries to get the order ids need to be addressed too.
Some context
The query to count orders pending synchronization runs in the following cases:
woocommerce_custom_orders_table_enabled
option (which would otherwise circumvent the above): if there's at least one order pending synchronization, trying to change the value of the option throws an exception (side note: Add the wc_allow_changing_orders_storage_while_sync_is_pending filter #39988 will actually allow to circumvent this by using a dedicated filter).wp wc cot count/sync/enable/disable
commands.When trying to come up with a solution it's useful to take in account the following:
id >
andid <
clauses, as usingLIMIT
doesn't help) the query execution time stays under one second.The (rough idea of a) solution
A possible solution could be doing the counting process in chunks of 100000 orders. This would require first obtaining the minimum and maximum order ids in the database, then doing a series of queries with
WHERE id>X AND id<X+100000
, with X increasing by 100000 every time.When running the CLI tool this is pretty straightforward, but when changing the authoritative table via UI multiple requests (and some kind of feedback for the user) would be needed. Scheduled actions could be used in the same way as it's done now for synchronizing orders, but a more responsive approach could be turning the authoritative table selection part of the settings page into a "widget" that calls (via AJAX) a dedicated REST API endpoint for counting orders requiring synchronization, passing the minimum and maximum order ids to scan. Once the counting has completed, the UI to change the authoritative table can then be enabled if the resulting value is zero (it would always appear as disabled initially).
The obtained count could be cached and reused the next time the settings page is opened: it would be valid until any order is created, modified or deleted.
Maybe this AJAX + REST API approach could be used for the orders synchronization too, if the user is willing to keep the settings page open while the process is running (and if the page is closed, the process could continue anyway via scheduled actions).
And this is what's in my mind for now regarding this problem. Comments welcome!
Beta Was this translation helpful? Give feedback.
All reactions