Analisi e Diagnostica del Database WooCommerce
Identificazione delle Tabelle Critiche
La prima operazione è mappare le tabelle che consumano più spazio e risorse. Query fondamentale per ogni DBA:
-- Analisi dimensioni tabelle ordinate per peso
SELECT
table_name AS 'Tabella',
ROUND(((data_length + index_length) / 1024 / 1024), 2) AS 'Dimensione_MB',
ROUND((index_length / 1024 / 1024), 2) AS 'Indici_MB',
table_rows AS 'Righe_Stimate'
FROM information_schema.TABLES
WHERE table_schema = 'nome_database'
ORDER BY (data_length + index_length) DESC
LIMIT 20;
Le tabelle critiche in installazioni WooCommerce di grandi dimensioni sono invariabilmente:
- wp_posts: prodotti, ordini, varianti
- wp_postmeta: metadati prodotti, attributi, campi custom
- wp_options: configurazioni, transient, autoload
- wp_woocommerce_order_items: righe ordine
- wp_woocommerce_order_itemmeta: metadati righe ordine
- wp_wc_product_meta_lookup: tabella di lookup per query prodotti
- wp_actionscheduler_actions: coda job asincroni
Analisi delle Query Lente con MySQL Slow Query Log
Attivare lo slow query log è obbligatorio per identificare i colli di bottiglia. Configurazione runtime:
-- Attivazione slow query log (sessione corrente)
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 2; -- Query oltre 2 secondi
SET GLOBAL log_queries_not_using_indexes = 1;
SET GLOBAL slow_query_log_file = '/var/log/mysql/slow-query.log';
Per configurazione permanente, editare /etc/mysql/mariadb.conf.d/50-server.cnf:
[mysqld]
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow-query.log
long_query_time = 2
log_queries_not_using_indexes = 1
Analisi con Percona Toolkit:
# Installazione pt-query-digest
apt-get install percona-toolkit
# Analisi log con aggregazione per query pattern
pt-query-digest /var/log/mysql/slow-query.log > slow-query-report.txt
# Top 10 query più lente
pt-query-digest --limit 10 --order-by Query_time:sum /var/log/mysql/slow-query.log
Monitoraggio Performance con Query Monitor
Query Monitor identifica in tempo reale query duplicate e pattern N+1. Installazione:
# Via WP-CLI
wp plugin install query-monitor --activate
# Configurazione wp-config.php per debug SQL
define('SAVEQUERIES', true);
define('QM_ENABLE_CAPS_PANEL', true);
Focus sui report:
- Queries by Component: individua plugin che generano query eccessive
- Duplicate Queries: query identiche eseguite multiple volte
- Queries by Caller: traccia la funzione/hook che genera la query
Ottimizzazione della Struttura delle Tabelle
Pulizia Tabella wp_options
La tabella wp_options è il primo punto critico. Transient scaduti e autoload eccessivo degradano ogni page load:
-- Rimozione transient scaduti
DELETE FROM wp_options
WHERE option_name LIKE '_transient_timeout_%'
AND option_value < UNIX_TIMESTAMP();
DELETE FROM wp_options
WHERE option_name LIKE '_transient_%'
AND option_name NOT LIKE '_transient_timeout_%'
AND option_name NOT IN (
SELECT REPLACE(option_name, '_transient_timeout_', '_transient_')
FROM wp_options
WHERE option_name LIKE '_transient_timeout_%'
);
-- Stessa operazione per site_transient
DELETE FROM wp_options
WHERE option_name LIKE '_site_transient_timeout_%'
AND option_value < UNIX_TIMESTAMP();
DELETE FROM wp_options
WHERE option_name LIKE '_site_transient_%'
AND option_name NOT LIKE '_site_transient_timeout_%'
AND option_name NOT IN (
SELECT REPLACE(option_name, '_site_transient_timeout_', '_site_transient_')
FROM wp_options
WHERE option_name LIKE '_site_transient_timeout_%'
);
Analisi autoload:
-- Identificare opzioni autoload pesanti (oltre 50KB)
SELECT
option_name,
LENGTH(option_value) AS size_bytes,
ROUND(LENGTH(option_value)/1024, 2) AS size_kb
FROM wp_options
WHERE autoload = 'yes'
ORDER BY LENGTH(option_value) DESC
LIMIT 50;
Disabilitare autoload per opzioni non critiche:
-- Opzioni WooCommerce che non richiedono autoload
UPDATE wp_options SET autoload = 'no'
WHERE option_name IN (
'woocommerce_meta_box_errors',
'woocommerce_thumbnail_image_width',
'woocommerce_thumbnail_image_height',
'_transient_wc_count_comments',
'action_scheduler_lock_async-request-runner'
);
Ottimizzazione Tabelle Post e Postmeta
Eliminazione revisioni, bozze automatiche e metadati orfani:
-- Backup preventivo
CREATE TABLE wp_posts_backup AS SELECT * FROM wp_posts;
CREATE TABLE wp_postmeta_backup AS SELECT * FROM wp_postmeta;
-- Eliminazione revisioni oltre 30 giorni (mantenere ultime 3 per post)
DELETE p1 FROM wp_posts p1
INNER JOIN (
SELECT post_parent, MAX(ID) as max_id
FROM wp_posts
WHERE post_type = 'revision'
AND post_date < DATE_SUB(NOW(), INTERVAL 30 DAY) GROUP BY post_parent HAVING COUNT(*) > 3
) p2 ON p1.post_parent = p2.post_parent
WHERE p1.post_type = 'revision'
AND p1.ID < p2.max_id - 3;
-- Eliminazione bozze automatiche
DELETE FROM wp_posts
WHERE post_status = 'auto-draft'
AND post_modified < DATE_SUB(NOW(), INTERVAL 7 DAY);
-- Eliminazione post nel cestino da oltre 30 giorni
DELETE FROM wp_posts
WHERE post_status = 'trash'
AND post_modified < DATE_SUB(NOW(), INTERVAL 30 DAY);
-- Pulizia postmeta orfani (nessun post corrispondente)
DELETE pm FROM wp_postmeta pm
LEFT JOIN wp_posts p ON pm.post_id = p.ID
WHERE p.ID IS NULL;
-- Ottimizzazione fisica tabelle
OPTIMIZE TABLE wp_posts;
OPTIMIZE TABLE wp_postmeta;
Gestione Sessioni WooCommerce
Le sessioni WooCommerce accumulate degradano drasticamente le performance. Soluzione multilivello:
-- Pulizia sessioni scadute (esecuzione manuale)
DELETE FROM wp_woocommerce_sessions
WHERE session_expiry < UNIX_TIMESTAMP();
-- Verifica dimensione tabella prima/dopo
SELECT
ROUND((data_length + index_length) / 1024 / 1024, 2) AS 'Size_MB',
table_rows
FROM information_schema.TABLES
WHERE table_schema = 'nome_database'
AND table_name = 'wp_woocommerce_sessions';
Per infrastrutture di produzione, le sessioni devono essere gestite con Redis. Un ambiente con Redis object cache e MariaDB ottimizzato come quello fornito da webcreare-hosting.it elimina completamente il problema delle sessioni su database, delegando a Redis la gestione in memoria con eviction automatica. Configurazione Redis per sessioni WooCommerce:
// wp-config.php - Object cache Redis
define('WP_REDIS_HOST', '127.0.0.1');
define('WP_REDIS_PORT', 6379);
define('WP_REDIS_DATABASE', 1);
define('WP_REDIS_TIMEOUT', 1);
define('WP_REDIS_READ_TIMEOUT', 1);
// Configurazione sessioni WooCommerce su Redis
define('WC_SESSION_CACHE_GROUP', 'wc_session_id');
Cronjob per pulizia residuale su database:
# Crontab entry - ogni 6 ore
0 */6 * * * mysql -u username -p'password' database_name -e "DELETE FROM wp_woocommerce_sessions WHERE session_expiry < UNIX_TIMESTAMP();" > /dev/null 2>&1
Pulizia Log e Tabelle Temporanee
Action Scheduler e log WooCommerce crescono indefinitamente:
-- Pulizia Action Scheduler (azioni completate oltre 30 giorni)
DELETE FROM wp_actionscheduler_actions
WHERE status = 'complete'
AND scheduled_date_gmt < DATE_SUB(NOW(), INTERVAL 30 DAY);
-- Pulizia log Action Scheduler
DELETE FROM wp_actionscheduler_logs
WHERE log_date_gmt < DATE_SUB(NOW(), INTERVAL 30 DAY);
-- Reset completo Action Scheduler (situazioni critiche)
TRUNCATE TABLE wp_actionscheduler_actions;
TRUNCATE TABLE wp_actionscheduler_logs;
TRUNCATE TABLE wp_actionscheduler_groups;
TRUNCATE TABLE wp_actionscheduler_claims;
-- Pulizia webhook logs WooCommerce
DELETE FROM wp_wc_webhooks
WHERE date_created < DATE_SUB(NOW(), INTERVAL 90 DAY);
-- Pulizia status logs WooCommerce
DELETE FROM wp_woocommerce_log
WHERE timestamp < DATE_SUB(NOW(), INTERVAL 30 DAY);
-- Ottimizzazione tabelle
OPTIMIZE TABLE wp_actionscheduler_actions;
OPTIMIZE TABLE wp_actionscheduler_logs;
Indicizzazione Strategica del Database
Creazione Indici Custom per WooCommerce
Gli indici standard di WordPress sono insufficienti per query WooCommerce complesse. Indici custom fondamentali:
-- Indice composite post_type + post_status + post_date
-- Accelera query shop/archivi prodotti
CREATE INDEX idx_post_type_status_date
ON wp_posts(post_type, post_status, post_date);
-- Indice per query meta_key + meta_value
-- Essenziale per filtri prodotti (prezzo, stock, attributi)
CREATE INDEX idx_meta_key_value
ON wp_postmeta(meta_key, meta_value(50));
-- Indice composite meta_key + post_id
-- Ottimizza JOIN tra posts e postmeta
CREATE INDEX idx_meta_key_post_id
ON wp_postmeta(meta_key, post_id);
-- Indice per order items lookup
CREATE INDEX idx_order_item_type
ON wp_woocommerce_order_items(order_id, order_item_type);
-- Indice per order itemmeta
CREATE INDEX idx_order_item_meta
ON wp_woocommerce_order_itemmeta(order_item_id, meta_key);
-- Indice per product lookup table (WC 3.6+)
CREATE INDEX idx_product_stock_status
ON wp_wc_product_meta_lookup(stock_status, product_id);
CREATE INDEX idx_product_price
ON wp_wc_product_meta_lookup(min_price, max_price);
Analisi e Ottimizzazione Indici Esistenti
Identificare indici con cardinalità zero o duplicati:
-- Analisi cardinalità indici
SELECT
TABLE_NAME,
INDEX_NAME,
SEQ_IN_INDEX,
COLUMN_NAME,
CARDINALITY,
INDEX_TYPE
FROM information_schema.STATISTICS
WHERE TABLE_SCHEMA = 'nome_database'
AND TABLE_NAME LIKE 'wp_%'
ORDER BY TABLE_NAME, INDEX_NAME, SEQ_IN_INDEX;
-- Identificare indici con cardinalità nulla (inefficaci)
SELECT
TABLE_NAME,
INDEX_NAME,
GROUP_CONCAT(COLUMN_NAME ORDER BY SEQ_IN_INDEX) AS columns
FROM information_schema.STATISTICS
WHERE TABLE_SCHEMA = 'nome_database'
AND CARDINALITY IS NULL OR CARDINALITY = 0
GROUP BY TABLE_NAME, INDEX_NAME;
Aggiornamento statistiche indici (operazione critica post-ottimizzazione):
-- Analisi tabelle per aggiornare statistiche
ANALYZE TABLE wp_posts, wp_postmeta, wp_options,
wp_woocommerce_order_items, wp_woocommerce_order_itemmeta,
wp_wc_product_meta_lookup;
-- Verifica utilizzo indici con EXPLAIN
EXPLAIN SELECT * FROM wp_posts
WHERE post_type = 'product'
AND post_status = 'publish'
ORDER BY post_date DESC
LIMIT 10;
Indici Composite per Query Complesse
Query WooCommerce richiedono spesso indici multi-colonna:
-- Indice per query prodotti pubblicati ordinati per data
CREATE INDEX idx_product_status_date
ON wp_posts(post_type(20), post_status(20), post_


