WordPress לא מנקה אוטומטית. תגובות שסומנו spam, פוסטים שנמחקו ל-Trash, ושורות meta של פוסטים שכבר לא קיימים - כל אלה מצטברים שנים ומנפחים את הטבלאות wp_comments, wp_commentmeta, wp_posts ו-wp_postmeta. באתרי בלוג ותיקים אלה לעיתים מאות אלפי שורות. הן משפיעות על כל שאילתת SELECT שעוברת בטבלאות הללו - ארכיון תגובות, RSS feed, ספירת תגובות בכל פוסט, חיפוש פנימי - ומגדילות גיבויים פי 2-5.
למה זה משנה
בעוד שאילתה שמסננת לפי post_status='publish' אינה איטית בעצמה, MySQL חייב להמיר את ה-WHERE על כל השורות בטבלה לפני שיכול להחזיר תוצאות (אם ה-index לא אופטימלי). באתר עם 1,000 פוסטים פעילים ו-50,000 פוסטים ב-Trash, השאילתה רצה על 51,000 שורות במקום על 1,000. ההבדל מורגש בלולאת arrays/RSS, בעמודי ארכיון, ובכל מקום שסופר תגובות. בנוסף, גודל קבצי הגיבוי גדל פי 5 - גיבוי שלקח 5 דקות לוקח 25 דקות, וייצוא ל-staging הופך כבד מיותר.
ב-Akismet סטטיסטיקות אומרות שאתר ממוצע מקבל 200-500 spam ביום אחרי שנתיים פעילות. בלי ניקוי שוטף, אחרי שנתיים יש לך 150K+ שורות זבל. כל אחת תופסת מקום, כל אחת מטופלת ב-rebuild של index, כל אחת בגיבוי.
איך לזהות
שאילתות לזיהוי הזבל:
-- ספירת spam ותגובות שנמחקו
SELECT comment_approved, COUNT(*) FROM wp_comments
GROUP BY comment_approved;
-- ספירת פוסטים לפי status
SELECT post_status, COUNT(*) FROM wp_posts
GROUP BY post_status;
-- שורות postmeta יתומות (פוסט שכבר לא קיים)
SELECT COUNT(*) FROM wp_postmeta pm
LEFT JOIN wp_posts p ON pm.post_id = p.ID
WHERE p.ID IS NULL;אם אתה רואה אלפי spam או trash או commentmeta יתום - יש כאן עבודה.
איך לתקן
הפתרון הכי בטוח הוא ה-UI של WordPress: תגובות > Spam > Empty Spam; תגובות > Trash > Empty Trash; פוסטים > Trash > Empty Trash; וחזור על כך לכל post type מותאם (Pages, Products, Forms וכו'). אם יש WP-CLI:
wp comment delete $(wp comment list --status=spam --format=ids) --force
wp comment delete $(wp comment list --status=trash --format=ids) --force
wp post delete $(wp post list --post_status=trash --format=ids --post_type=any) --forceלניקוי שורות meta יתומות:
DELETE pm FROM wp_postmeta pm
LEFT JOIN wp_posts p ON pm.post_id = p.ID
WHERE p.ID IS NULL;
DELETE cm FROM wp_commentmeta cm
LEFT JOIN wp_comments c ON cm.comment_id = c.comment_id
WHERE c.comment_id IS NULL;לאחר המחיקות, הרץ OPTIMIZE TABLE wp_comments, wp_commentmeta, wp_posts, wp_postmeta; כדי להחזיר את המקום הפיזי בקבצי ה-InnoDB. בלי OPTIMIZE, גודל הקובץ נשאר זהה למרות שמספר השורות ירד.
למניעה עתידית: התקן Akismet (חינמי לאתרים אישיים) או Antispam Bee. הם חוסמים 99% מ-spam-bots בלי CAPTCHA. הוסף ל-wp-config.php כדי לרוקן Trash אחרי 7 ימים: define('EMPTY_TRASH_DAYS', 7);
טעויות נפוצות
הטעות הראשונה: למחוק תגובות "pending" יחד עם spam - אלה תגובות לגיטימיות שמחכות לאישור. בדוק לפני שאתה מוחק bulk. הטעות השנייה: להריץ DELETE על wp_postmeta בלי JOIN ל-wp_posts - יש סיכון למחוק שורות שכן קשורות לפוסט קיים. השתמש תמיד ב-LEFT JOIN ... WHERE p.ID IS NULL. הטעות השלישית: לשכוח OPTIMIZE TABLE אחרי - InnoDB לא משחרר מקום אוטומטית, וגיבויים יישארו כבדים. הטעות הרביעית: למחוק revisions של פוסטים פעילים בטעות תוך כדי - גם הן יש להן post_status = 'inherit' ולא trash, אז כללי הסינון שונים.
בדיקה לאחר תיקון
הרץ שוב את שאילתות הספירה - מספר השורות בכל סטטוס spam/trash צריך להיות 0. בדוק את גודל ה-DB עם SELECT SUM(data_length+index_length)/1024/1024 FROM information_schema.tables WHERE table_schema=DATABASE(); - אמור להיות קטן יותר ב-30-60%. בדוק גודל גיבוי ב-UpdraftPlus - יקטן בהתאם. ב-Query Monitor, השווה זמני שאילתה של ארכיון תגובות לפני ואחרי - אמור להיות מהיר ב-30-50%.