-
Notifications
You must be signed in to change notification settings - Fork 10
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
WPML plugin: see if we can make its tables any faster. #36
Comments
WPML is not open source. But I have obtained a dev license. |
I can provide you a license key if you like. |
pixelBrain -- Can you provide me with SHOW CREATE TABLE for the tables and some sample queries? (I can probably get started faster with simply that info.)
Rick Jamesemail: ***@***.***
On Friday, June 3, 2022, 02:01:29 PM PDT, pixelBrain ***@***.***> wrote:
I can provide you a license key if you like.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.Message ID: ***@***.***>
|
I did a quick "Monitor" and pulled out these slowest queries. Hopefully this could help you with a starting point:
|
These arent all the tables, but it's the tables that had the most rows and/or largest in my db:
CREATE TABLE CREATE TABLE CREATE TABLE CREATE TABLE CREATE TABLE CREATE TABLE CREATE TABLE CREATE TABLE ` |
Thanks. Here's a first pass:
Without seeing the `CREATE TABLEs`, My index suggestions may be redundant.
I assume "s" and "i" are the digests for literal "string" and "integer"?
Skip to the end to see the summary of index suggestions.Some coding suggestions are interspersed.
----------------------------------------
Query 1:
Is this looking for all missing entry in wp_icl_translations? What will ID be used for then?
SELECT p.ID FROM wp_posts p LEFT JOIN wp_icl_translations i ON CONCAT(s, p.post_type ) = i.element_type AND i.element_id = p.ID WHERE p.post_type = s AND i.language_code IS NULL
Index recommendations (In this case, they are both "composite" and "covering"):
wp_posts: INDEX(post_type, ID) wp_icl_translations: INDEX(element_type, element_id, language_code) When adding a composite index, DROP index(es) with the same leading columns.That is, when you have both INDEX(a) and INDEX(a,b), toss the former.
Re: CONCAT: In general, an expression in ON _may_ be problematical. (It may _not_ be a problem in this particular case.)
----------------------------------------
Query 2: (I took the liberty of shortening an alias.)
SELECT i.element_id, tax.term_id, tax.taxonomy FROM wp_icl_translations i JOIN wp_term_taxonomy tax ON i.element_id = tax.term_taxonomy_id AND i.element_type = CONCAT(s, tax.taxonomy) JOIN wp_terms terms ON terms.term_id = tax.term_id WHERE tax.term_id != tax.term_taxonomy_id
wp_icl_translations: INDEX(element_type, element_id) tax: INDEX(term_id, term_taxonomy_id, taxonomy) terms: INDEX(term_id) Is `term_id` the `PRIMARY KEY` for `terms`? If so, then do not add `INDEX(term_id)` it would be redundant and wasteful.
You _may_ be able to remove
JOIN wp_terms terms ON terms.term_id = tax.term_id
No other uses for that table are made. Its only purpose is to verify that there is a matching row in that table.
Removing that JOIN is likely to speed up the query.
----------------------------------------Query 3:
SELECT wpml_translations.translation_id, wpml_translations.language_code, wpml_translations.element_id, wpml_translations.source_language_code, wpml_translations.element_type, NULLIF(wpml_translations.source_language_code, s) IS NULL AS original , tm.name, tm.term_id, COUNT(tr.object_id) AS instances FROM wp_icl_translations wpml_translations LEFT JOIN wp_term_taxonomy tt ON wpml_translations.element_id=tt.term_taxonomy_id LEFT JOIN wp_terms tm ON tt.term_id = tm.term_id LEFT JOIN wp_term_relationships tr ON tr.term_taxonomy_id=tt.term_taxonomy_id WHERE 1 AND wpml_translations.trid=i GROUP BY tm.term_id
wpml_translations: INDEX(trid) wp_terms: INDEX(term_id, name) -- unless it has PRIMARY KEY(term_id) wp_term_taxonomy: INDEX(term_taxonomy_id, object_id) tt: INDEX(term_taxonomy_id, term_id)
This query may be formulated wrong. It is a common problem -- in both computation (the COUNT) and in performance:
1. JOIN several tables -- this builds a temp table with all the valid combinations.2. Do the aggregates (such as COUNT) on the large temp table.3. Shrink the results using GROUP BY.
Please verify that the COUNTs look correct. Also tell me more about the LEFT JOINs -- are they typically 0 or 1, or 0 or many maybe they should be 1 to many.
Have you tested this with MySQL 8.0? Cf: "ONLY_FULL_GROUP_BY".
I will look more closely after you have provided some answers.
Is wp_terms a simple lookup table that maps id <=> name?
Are tr and tt many-to-many mapping tables? There is a common performance issue in such; I need to see SHOW CREATE TABLE to verify.
"NULLIF(wpml_translations.source_language_code, s) IS NULL AS original" -- seems a bit contorted; what is the intent? Maybe I can simplify it.
----------------------------------------Query 4:
SELECT i.translation_id, i.element_id, i.language_code, wpml_translations.source_language_code, i.trid, i.element_type FROM wp_icl_translations i JOIN wp_term_taxonomy tax ON i.element_id = tax.term_taxonomy_id AND i.element_type = CONCAT(s, tax.taxonomy) JOIN wp_icl_translations tridt ON tridt.element_type = i.element_type AND tridt.trid = i.trid WHERE tridt.trid = ( SELECT trid FROM wp_icl_translations i2 JOIN wp_term_taxonomy tax ON i2.element_id = tax.term_taxonomy_id AND i2.element_type = CONCAT(s, tax.taxonomy) WHERE i2.element_id = i LIMIT 1 )
tax: INDEX(term_taxonomy_id, taxonomy) wp_icl_translations: INDEX(trid, element_type) wp_icl_translations: INDEX(element_id, element_type)
---------------------------------------- Summary of new indexes (eliminating dups, etc)
wp_term_taxonomy: -- nothing new if term_taxonomy_id is the PK
wp_icl_translations: INDEX(element_type, element_id, language_code) wp_icl_translations: INDEX(trid, element_type)
wp_posts: INDEX(post_type, ID)
wp_terms: INDEX(term_id, name) -- unless it has PRIMARY KEY(term_id)
…----------------------------------------
FROM wp_icl_translations wpml_translations(This naming is confusing; I hope I did not mess things up.)
Rick Jamesemail: ***@***.***
On Friday, June 3, 2022, 02:45:56 PM PDT, pixelBrain ***@***.***> wrote:
pixelBrain -- Can you provide me with SHOW CREATE TABLE for the tables and some sample queries? (I can probably get started faster with simply that info.) Rick Jamesemail: @.*** On Friday, June 3, 2022, 02:01:29 PM PDT, pixelBrain @.> wrote: I can provide you a license key if you like. — Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you are subscribed to this thread.Message ID: @.>
I did a quick "Monitor" and pulled out these slowest queries. Hopefully this could help you with a starting point:
SELECT p.ID FROM wp_posts p LEFT JOIN wp_icl_translations i ON CONCAT(s, p.post_type ) = i.element_type AND i.element_id = p.ID WHERE p.post_type = s AND i.language_code IS NULL
SELECT wpml_translations.element_id, tax.term_id, tax.taxonomy FROM wp_icl_translations wpml_translations JOIN wp_term_taxonomy tax ON wpml_translations.element_id = tax.term_taxonomy_id AND wpml_translations.element_type = CONCAT(s, tax.taxonomy) JOIN wp_terms terms ON terms.term_id = tax.term_id WHERE tax.term_id != tax.term_taxonomy_id
SELECT wpml_translations.translation_id, wpml_translations.language_code, wpml_translations.element_id, wpml_translations.source_language_code, wpml_translations.element_type, NULLIF(wpml_translations.source_language_code, s) IS NULL AS original , tm.name, tm.term_id, COUNT(tr.object_id) AS instances FROM wp_icl_translations wpml_translations LEFT JOIN wp_term_taxonomy tt ON wpml_translations.element_id=tt.term_taxonomy_id LEFT JOIN wp_terms tm ON tt.term_id = tm.term_id LEFT JOIN wp_term_relationships tr ON tr.term_taxonomy_id=tt.term_taxonomy_id WHERE 1 AND wpml_translations.trid=i GROUP BY tm.term_id
SELECT wpml_translations.translation_id, wpml_translations.element_id, wpml_translations.language_code, wpml_translations.source_language_code, wpml_translations.trid, wpml_translations.element_type FROM wp_icl_translations wpml_translations JOIN wp_term_taxonomy tax ON wpml_translations.element_id = tax.term_taxonomy_id AND wpml_translations.element_type = CONCAT(s, tax.taxonomy) JOIN wp_icl_translations tridt ON tridt.element_type = wpml_translations.element_type AND tridt.trid = wpml_translations.trid WHERE tridt.trid = (SELECT trid FROM wp_icl_translations wpml_translations JOIN wp_term_taxonomy tax ON wpml_translations.element_id = tax.term_taxonomy_id AND wpml_translations.element_type = CONCAT(s, tax.taxonomy) WHERE element_id = i LIMIT 1)
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you commented.Message ID: ***@***.***>
|
Thanks.translation_id is UNIQUE in one table and PRIMARY in another. That sort of means they could be merged into a single table. Thoughts on that?
As with WP, `BIGINT` is overkill for many numeric fields. It occupies 8 bytes. `INT UNSIGNED` takes 4 bytes but has a limit of 4 billion.
UUIDs could be compressed into `BINARY(16)` (16 bytes) instead of `VARCHAR(36)`. However, the code for such is different between MySQL and MariaDB, so it may be unwise to use the builtin techniques.
Whenever there is both a PRIMARY KEY and a UNIQUE, I wonder if the PK could be removed. (This may not be worth pursuing.) I'm thinking especially of rid/trid/translation_id.
Inconsistent: language vs language_code, VARCHAR(10) vs (7). (Not serious.)
The indexes are mostly in good shape.
Where I mentioned "element_type, element_id", the order of those two probably does not matter. Hence, my suggestions on wp_icl_translations are already in place.
Rick Jamesemail: ***@***.***
On Friday, June 3, 2022, 03:15:46 PM PDT, pixelBrain ***@***.***> wrote:
Also:
CREATE TABLE wp_icl_translate(tidbigint(20) unsigned NOT NULL AUTO_INCREMENT,job_idbigint(20) unsigned NOT NULL,content_idbigint(20) unsigned NOT NULL,timestamptimestamp NOT NULL DEFAULT current_timestamp(),field_typevarchar(160) COLLATE utf8mb4_unicode_ci NOT NULL,field_wrap_tagvarchar(16) COLLATE utf8mb4_unicode_ci NOT NULL,field_formatvarchar(16) COLLATE utf8mb4_unicode_ci NOT NULL,field_translatetinyint(4) NOT NULL,field_datalongtext COLLATE utf8mb4_unicode_ci NOT NULL,field_data_translatedlongtext COLLATE utf8mb4_unicode_ci NOT NULL,field_finished tinyint(4) NOT NULL DEFAULT 0, PRIMARY KEY (tid), KEY job_id (job_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1271621 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
CREATE TABLE wp_icl_translation_status (
rid bigint(20) NOT NULL AUTO_INCREMENT,
translation_id bigint(20) NOT NULL,
status tinyint(4) NOT NULL,
translator_id bigint(20) NOT NULL,
needs_update tinyint(4) NOT NULL,
md5 varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL,
translation_service varchar(16) COLLATE utf8mb4_unicode_ci NOT NULL,
translation_package longtext COLLATE utf8mb4_unicode_ci NOT NULL,
timestamp timestamp NOT NULL DEFAULT current_timestamp(),
links_fixed tinyint(4) NOT NULL DEFAULT 0,
_prevstate longtext COLLATE utf8mb4_unicode_ci DEFAULT NULL,
batch_id int(11) NOT NULL DEFAULT 0,
uuid varchar(36) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
tp_id int(11) DEFAULT NULL,
tp_revision int(11) NOT NULL DEFAULT 1,
ts_status text COLLATE utf8mb4_unicode_ci DEFAULT NULL,
review_status enum('NEEDS_REVIEW','EDITING','ACCEPTED') COLLATE utf8mb4_unicode_ci DEFAULT NULL,
ate_comm_retry_count int(11) unsigned DEFAULT 0,
PRIMARY KEY (rid),
UNIQUE KEY translation_id (translation_id)
) ENGINE=InnoDB AUTO_INCREMENT=1104345 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
CREATE TABLE wp_icl_translations (
translation_id bigint(20) NOT NULL AUTO_INCREMENT,
element_type varchar(36) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'post_post',
element_id bigint(20) DEFAULT NULL,
trid bigint(20) NOT NULL,
language_code varchar(7) COLLATE utf8mb4_unicode_ci NOT NULL,
source_language_code varchar(7) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
PRIMARY KEY (translation_id),
UNIQUE KEY trid_lang (trid,language_code),
UNIQUE KEY el_type_id (element_type,element_id),
KEY id_type_language (element_id,element_type,language_code)
) ENGINE=InnoDB AUTO_INCREMENT=2000609 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
CREATE TABLE wp_icl_strings (
id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
language varchar(7) COLLATE utf8mb4_unicode_ci NOT NULL,
context varchar(160) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
name varchar(160) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
value longtext COLLATE utf8mb4_unicode_ci NOT NULL,
string_package_id bigint(20) unsigned DEFAULT NULL,
type varchar(40) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'LINE',
title varchar(160) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
status tinyint(4) NOT NULL,
gettext_context mediumtext COLLATE utf8mb4_unicode_ci NOT NULL,
domain_name_context_md5 varchar(32) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
location bigint(20) unsigned DEFAULT NULL,
wrap_tag varchar(16) COLLATE utf8mb4_unicode_ci NOT NULL,
word_count int(10) unsigned DEFAULT NULL,
translation_priority varchar(160) COLLATE utf8mb4_unicode_ci NOT NULL,
PRIMARY KEY (id),
UNIQUE KEY uc_domain_name_context_md5 (domain_name_context_md5) USING BTREE,
KEY language_context (language,context),
KEY string_package_id (string_package_id),
KEY icl_strings_name (name),
KEY icl_strings_translation_priority (translation_priority),
KEY context (context)
) ENGINE=InnoDB AUTO_INCREMENT=1670009 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
CREATE TABLE wp_icl_string_positions (
id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
string_id bigint(20) NOT NULL,
kind tinyint(4) DEFAULT NULL,
position_in_page varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
PRIMARY KEY (id),
KEY string_id (string_id)
) ENGINE=InnoDB AUTO_INCREMENT=38105 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
CREATE TABLE wp_icl_string_translations (
id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
string_id bigint(20) unsigned NOT NULL,
language varchar(10) COLLATE utf8mb4_unicode_ci NOT NULL,
status tinyint(4) NOT NULL,
value longtext COLLATE utf8mb4_unicode_ci DEFAULT NULL,
mo_string longtext COLLATE utf8mb4_unicode_ci DEFAULT NULL,
translator_id bigint(20) unsigned DEFAULT NULL,
translation_date timestamp NOT NULL DEFAULT current_timestamp(),
batch_id int(11) NOT NULL DEFAULT 0,
translation_service varchar(16) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
PRIMARY KEY (id),
UNIQUE KEY string_language (string_id,language),
KEY status (status)
) ENGINE=InnoDB AUTO_INCREMENT=1638251 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
CREATE TABLE wp_icl_translate_job (
job_id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
rid bigint(20) unsigned NOT NULL,
translator_id int(10) unsigned NOT NULL,
translated tinyint(3) unsigned NOT NULL DEFAULT 0,
manager_id int(10) unsigned NOT NULL,
revision int(10) unsigned DEFAULT NULL,
title varchar(160) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
deadline_date datetime DEFAULT NULL,
completed_date datetime DEFAULT NULL,
editor varchar(16) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
editor_job_id bigint(20) unsigned DEFAULT NULL,
automatic tinyint(3) unsigned NOT NULL DEFAULT 0,
ate_sync_count int(6) unsigned DEFAULT 0,
PRIMARY KEY (job_id),
KEY rid (rid,translator_id)
) ENGINE=InnoDB AUTO_INCREMENT=32594 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
CREATE TABLE wp_icl_string_status (
id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
rid bigint(20) NOT NULL,
string_translation_id bigint(20) NOT NULL,
timestamp timestamp NOT NULL DEFAULT current_timestamp(),
md5 varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL,
PRIMARY KEY (id),
KEY string_translation_id (string_translation_id)
) ENGINE=InnoDB AUTO_INCREMENT=3214 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
CREATE TABLE wp_icl_languages_translations (
id int(11) NOT NULL AUTO_INCREMENT,
language_code varchar(7) COLLATE utf8mb4_unicode_ci NOT NULL,
display_language_code varchar(7) COLLATE utf8mb4_unicode_ci NOT NULL,
name varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
PRIMARY KEY (id),
UNIQUE KEY language_code (language_code,display_language_code)
) ENGINE=InnoDB AUTO_INCREMENT=5597 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
CREATE TABLE wp_icl_string_batches (
id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
string_id bigint(20) unsigned NOT NULL,
batch_id bigint(20) unsigned NOT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB AUTO_INCREMENT=7459 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
`
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you commented.Message ID: ***@***.***>
|
Thanks, im definitely out of my depth here on optimizing the queries. Maybe someone else will know more. |
Thanks for this info, @tridoan-px @tridoan @rjasdf . It looks like the It's hard to know more without actual data to use with EXPLAIN ANALYZE statements. The sample definition you provided for that table shows it's large at a couple of million rows. There may be an opportunity to change the primary key from the autoincrementing @tridoan is there any chance you can provide dumps of these tables for us to use in analysis? (I know you might have to answer "no" -- your data is, of course, yours.) wp_icl_translations |
Here are a couple of query monitors and the SQL defining a WordPress + WPML database. They're from an absurdly small WPML site, so query-planner index choices are distorted. But the monitors do show queries like the one in this issue. One monitor is WITH the high-perf keys and the other without. The SQL is with the high-perf keys. Notice that the site in question has a persistent object cache; that gets rid of a lot of chaff queries to and from the VerySmallWPMLSiteSQLandMonitors.zip (The WPML folks were kind enough to grant me a dev license.) |
hi @OllieJones , is it possible we can chat offline? I can give you some access if needed, but am unable to publicly provide here. Sorry for the delay, been pulled too many ways the past week |
Sure, please sent me an email . Address on my github profile. (I've been away on vac. back in the saddle now.) |
Any update on optimizing wpml ? :) |
@ufo56 - Are you willing to test the indexes I supplied above? |
Yes, of course. WPML String Translation mysql query performance ( wp_icl_strings) sucks so much that i dont have words. EDIT: If you need also need whatever testing environment, i can give you. I have here 90k product shop with 2 languages, slowest component is WPML WPML Strings Translation ON https://i.imgur.com/UMqg3ws.png |
#1265 - Data truncated for column 'element_id' at row 770 No primary keys added |
Ugh! Do you happen to know the values of those 3 columns for the 770th row? I see that two are BIGINTs and one is VARCHAR(36); did any of those datatypes change? |
EDIT: There are rows where element_id is NULL, seems that is the problem here. Removed rows with NULL element_id and now it worked |
Further research about WPML suggests that using a persistent object cache plugin will help performance with WPML. Their developers went to a lot of trouble to cache results of SQL queries. |
Unfortunately there are many issues with object caches in combination with WPML. We tried multiple of them and always had problems, such as showing old translations or 404 redirects on translated pages. |
Can we look at the WPML plugin's indexes to find opportunities for speedups? https://wpml.org/
Per this request. https://wordpress.org/support/topic/please-add-wpml-support/
The text was updated successfully, but these errors were encountered: