Tabela wp_postmeta hrani dodatne podatke prispevkov, strani, izdelkov in naročil: vsako polje po meri, vsaka nastavitev vtičnika je ena vrstica. Lastnega čistilca nima. Ko odstraniš vtičnik, njegove vrstice večinoma ostanejo, ker le malo vtičnikov ob odhodu izbriše svoje podatke, po veliki menjavi različice pa lahko obtičijo tudi stara imena ključev.
Pri spletni trgovini tabela tako v letih zraste na milijone vrstic. To občutiš na treh mestih: poizvedbe s filtri (na primer filtri izdelkov) se upočasnijo, varnostno kopiranje in obnovitev trajata dlje, zmanjkuje pa tudi prostora na gostovanju.
1. Kako velika je tabela in kaj je v njej?
Velikost tabel vidiš v phpMyAdminu (skupina Podatkovne baze v cPanelu), na zavihku Struktura podatkovne baze. Porazdelitev vrstic po imenu ključa:
SELECT meta_key, COUNT(*) AS db
FROM 1vL7334_postmeta
GROUP BY meta_key
ORDER BY db DESC
LIMIT 40;
Predpona tabel (v primeru 1vL7334_) je na spletnih mestih, nameščenih z WP Toolkit, naključna; svojo izpiše ukaz wp db prefix, vidiš pa jo tudi na seznamu na levi strani phpMyAdmina. Iz ukazne vrstice lahko poizvedbo zaženeš z ukazom mysql; na strežnikih cPanel aWh wp db query ne deluje (proc_open je onemogočen). Nastavitev datoteke ~/.my.cnf z geslom opisuje članek o uporabi WP-CLI.
cd ~/public_html
P=$(wp db prefix); DB=$(wp config get DB_NAME)
mysql "$DB" -e "SELECT meta_key, COUNT(*) AS db FROM ${P}postmeta GROUP BY meta_key ORDER BY db DESC LIMIT 40"
2. Kaj je odveč?
Ključi odstranjenih vtičnikov. Predpona imen ključev večinoma kaže na vtičnik (_yoast_, _elementor_, _wc_, _aioseo_). Seznam primerjaj z nameščenimi vtičniki:
wp plugin list --fields=name,status
Če je družina ključev velika in njenega vtičnika ni več na seznamu, jo najverjetneje lahko izbrišeš. Če nisi prepričan, poišči ime ključa: dokumentacija ali forum vtičnikov večinoma pove, kateremu vtičniku pripada.
Osirotele vrstice, katerih prispevek ne obstaja več (na primer po izbrisanih naročilih ali prispevkih, dokončno izbrisanih iz koša):
SELECT COUNT(*)
FROM 1vL7334_postmeta pm
LEFT JOIN 1vL7334_posts p ON p.ID = pm.post_id
WHERE p.ID IS NULL;
Na zdravem spletnem mestu je to nič ali zelo majhno število.
Naročila WooCommerce. Novejši WooCommerce naročila hrani v lastnih tabelah (HPOS). Če je tvoje spletno mesto prešlo nanje in je sinhronizacija izklopljena, so stari podatki naročil morda še v tabeli wp_postmeta. Teh ne briši ročno, temveč z lastnim orodjem WooCommerce (WooCommerce › Nastavitve › Napredno › Funkcije), in šele ko se prepričaš, da so naročila v novih tabelah popolna.
3. Varnostna kopija
Preden karkoli izbrišeš, shrani podatkovno bazo:
mysqldump --single-transaction --no-tablespaces "$DB" > ~/postmeta-elott-$(date +%F).sql
tail -1 ~/postmeta-elott-$(date +%F).sql
Zadnja vrstica naj bo -- Dump completed on …. Primerna sta tudi zavihek Izvoz v phpMyAdminu in dnevna varnostna kopija JetBackup (obnovitev iz varnostne kopije).
4. Brisanje v majhnih delih
En sam velik DELETE na več sto tisoč vrsticah dolgo zaklene tabelo. Ker vsako shranjevanje prispevka in naročila piše v to tabelo, se spletno mesto ta čas upočasni, blagajna se lahko zatakne, operacija pa lahko naleti tudi na omejitev virov gostovanja. Raje briši v delih po 5000 vrstic, s kratkimi premori:
KULCS='_regibovitmeny_adat'
while :; do
N=$(mysql "$DB" -N -e "DELETE FROM ${P}postmeta WHERE meta_key = '${KULCS}' LIMIT 5000; SELECT ROW_COUNT();")
echo "izbrisano: $N"
[ "$N" -eq 0 ] && break
sleep 1
done
Izpiše vsak krog in se ustavi, ko ni več česa brisati. Za osirotele vrstice velja isti vzorec, poizvedba:
DELETE pm FROM 1vL7334_postmeta pm
LEFT JOIN 1vL7334_posts p ON p.ID = pm.post_id
WHERE p.ID IS NULL;
Te oblike MySQL ne dovoli z LIMIT; če je zadetkov veliko, briši po obsegih identifikatorjev (na primer AND pm.meta_id < 100000, nato < 200000) ali uporabi vtičnik za čiščenje, kot je WP-Optimize, ki prav tako dela po delih.
Brez SSH lahko iste poizvedbe zaženeš na zavihku SQL v phpMyAdminu; različico z LIMIT 5000 ponavljaj, dokler število prizadetih vrstic ne pade na nič.
5. Stiskanje tabele
Prostor izbrisanih vrstic se znotraj tabele sprosti, vendar datoteka na disku ne postane manjša in tudi varnostno kopiranje se ne pospeši, dokler tabele ne zgradiš znova:
mysql "$DB" -e "OPTIMIZE TABLE ${P}postmeta"
Opomba Table does not support optimize, doing recreate + analyze instead v odgovoru je normalna (pri tabeli InnoDB MySQL tako znova zgradi tabelo), bistveno je stanje OK v zadnji vrstici. Operacija za nekaj sekund do minut zaklene tabelo, zato jo zaženi v obdobju z malo prometa. V phpMyAdminu: označi tabelo in izberi operacijo Optimiziraj tabelo.
Preverjanje
Znova zaženi prvo poizvedbo ter primerjaj število vrstic in velikost tabele. Preglej pomembne dele spletnega mesta (strani izdelkov, filtre, blagajno, predloge graditelja strani): če kaj manjka, si izbrisal ključ, ki je še v uporabi, in ga lahko obnoviš iz varnostne kopije.
Če je poleg wp_postmeta počasen tudi skrbniški vmesnik, pomaga članek o samodejno nalaganih podatkih tabele wp_options; če podatkovna baza raste zaradi opravil v ozadju, preberi članek o Action Scheduler.