דילוג לתוכן הראשי
מסד נתוניםביצועיםאופטימיזציית מהירותאחסון וורדפרס

אופטימיזציית מסד הנתונים בוורדפרס — מה מאט אתרים ותיקים

למה אתר שהיה מהיר לפני שנתיים איטי היום, איך למצוא את השאילתות הכבדות, ומה בטוח לנקות במסד הנתונים — ומה לא.

אביר

אחראי מידע ותוכן

7 דקות קריאה
תוכן עניינים15 פרקים
  1. למה זה משנה כל כך
  2. החשוד הראשון: wp_options ו-autoload
  3. גרסאות פוסטים (Revisions)
  4. Transients
  5. טבלאות יתומות
  6. אינדקסים
  7. איתור שאילתות איטיות
  8. שני מקורות שקטים לניפוח
  9. מה קורה כשלא נוגעים בזה שנים
  10. תחזוקה שוטפת
  11. מה **לא** לעשות
  12. מתי הבעיה היא לא מסד הנתונים
  13. שאלות נפוצות
  14. שלוש נקודות לזכור
  15. איך נראה מסד נתונים בריא

אתר שהיה מהיר כשהושק ואיטי אחרי שנתיים, בלי ששיניתם דבר — הסיפור הזה כמעט תמיד מסתיים באותו מקום: מסד הנתונים.

הוא גדל בשקט. כל תוסף שהותקן והוסר השאיר שאריות. כל שמירה של פוסט יצרה גרסה. כל בקשת API שמרה ערך זמני שאיש לא ניקה.

למה זה משנה כל כך

בטעינת דף וורדפרס ללא מטמון, שאילתות מסד נתונים הן כרבע מהזמן. אבל ההשפעה גדולה יותר משנדמה, כי חלק מהשאילתות רצות לפני כל דבר אחר — לפני התבנית, לפני התוספים, לפני שהוחלט מה בכלל להציג.

הכבדה שם מכפילה את עצמה בכל בקשה.

החשוד הראשון: wp_options ו-autoload

מה קורה כאן

טבלת wp_options מחזיקה הגדרות. לכל שורה יש עמודה autoload. כל שורה המסומנת yes נטענת לזיכרון בכל טעינת דף — בין אם היא נחוצה ובין אם לא.

זו התכונה שהופכת את הטבלה מאחסון הגדרות למכשול ביצועים.

איך בודקים

SELECT ROUND(SUM(LENGTH(option_value))/1024/1024, 2) AS mb,
       COUNT(*) AS rows_count
FROM wp_options WHERE autoload = 'yes';
גודלמצב
מתחת ל-800KBתקין
800KB–2MBשווה בדיקה
2–5MBבעיה מורגשת
מעל 5MBבעיה חמורה

מי האשמים

SELECT option_name, ROUND(LENGTH(option_value)/1024, 1) AS kb
FROM wp_options WHERE autoload = 'yes'
ORDER BY LENGTH(option_value) DESC LIMIT 20;

השורות הגדולות הן בדרך כלל:

  • שאריות של תוספים שהוסרו. התוסף נמחק, ההגדרות נשארו — ונטענות לנצח.
  • לוגים שנשמרו כאופציה. תוספים מסוימים כותבים יומני פעילות לתוך wp_options. שדה אחד יכול להגיע למגה-בייט.
  • transients שפג תוקפם ולא נמחקו.
  • הגדרות בוני דפים — לעיתים מאות קילו-בייטים לגיטימיים.

מה לעשות

אל תמחקו לפי ניחוש. מחיקת אופציה של תוסף פעיל תשבור אותו.

הגישה הבטוחה:

  1. גבו את מסד הנתונים
  2. זהו לאיזה תוסף שייך כל ערך גדול (בדרך כלל לפי הקידומת בשם)
  3. אם התוסף כבר לא מותקן — בטוח למחוק
  4. אם הוא מותקן — בדקו אם אפשר לכבות את הלוג בהגדרות שלו

לחלק מהערכים אפשר פשוט לבטל את הטעינה האוטומטית במקום למחוק:

UPDATE wp_options SET autoload = 'no' WHERE option_name = 'some_huge_log';

הערך נשאר, אבל נטען רק כשמבקשים אותו במפורש.

גרסאות פוסטים (Revisions)

וורדפרס שומר גרסה בכל שמירה. פוסט שנערך 40 פעם מייצר 40 שורות בטבלת wp_posts, כל אחת עם התוכן המלא.

באתר עם 500 פוסטים זה יכול להיות 20,000 שורות מיותרות שמכבידות על כל שאילתה שסורקת את הטבלה.

הגבלה

ב-wp-config.php:

define( 'WP_POST_REVISIONS', 5 );

חמש גרסאות אחרונות — מספיק לחזור אחורה, בלי לאגור.

ניקוי הקיים

גבו קודם. אחר כך:

DELETE FROM wp_posts WHERE post_type = 'revision';
DELETE pm FROM wp_postmeta pm
  LEFT JOIN wp_posts p ON p.ID = pm.post_id
  WHERE p.ID IS NULL;

השאילתה השנייה חשובה: מחיקת פוסטים לבדה משאירה מטא יתומה, שהיא הרבה פעמים גדולה יותר מהפוסטים עצמם.

Transients

Transient הוא ערך זמני עם תאריך תפוגה — תוצאת API, מונה, נתון מחושב.

הבעיה: וורדפרס מוחק transient שפג רק כשמישהו מבקש אותו במפורש. transient שאיש לא ביקש נשאר בטבלה לנצח.

DELETE FROM wp_options
WHERE option_name LIKE '\_transient\_timeout\_%'
  AND option_value < UNIX_TIMESTAMP();

ואז את הערכים היתומים שנשארו בלי ה-timeout שלהם.

הערה חשובה: עם Redis כמטמון אובייקטים, transients נשמרים בזיכרון ולא בטבלה — והבעיה נעלמת מעצמה. זו עוד סיבה להפעיל אותו; הרחבנו במאמר מטמון בוורדפרס.

טבלאות יתומות

תוסף שהוסר לא תמיד מוחק את הטבלאות שיצר. אתר בן חמש שנים יכול לגרור עשר טבלאות של תוספים שאינם מותקנים.

SHOW TABLES;

כל טבלה שאינה בקידומת wp_ הסטנדרטית ואינה שייכת לתוסף פעיל היא מועמדת. ודאו לפני מחיקה — חלק מהתוספים משתמשים בשמות לא צפויים.

אינדקסים

אינדקס מאפשר למסד הנתונים למצוא שורות בלי לסרוק את כל הטבלה.

וורדפרס מגיע עם אינדקסים סבירים, אבל תוספים שיוצרים שדות מטא מותאמים לעיתים שוכחים לאנדקס אותם. שאילתה שמסננת לפי meta_key בלי אינדקס סורקת מיליוני שורות.

SELECT COUNT(*) FROM wp_postmeta;

מעל מיליון שורות באתר בינוני — סימן שמשהו מייצר מטא בכמות חריגה.

איתור שאילתות איטיות

Query Monitor

התוסף החשוב ביותר לאבחון. הוא מציג בכל דף:

  • כמה שאילתות רצו
  • כמה זמן לקחו
  • איזה תוסף אחראי לכל אחת

השורה האחרונה היא מה שהופך אותו לשימושי. במקום לנחש, אתם רואים שתוסף מסוים מייצר 340 שאילתות בדף הבית.

מדדי ייחוס: דף בית סביר מבצע 30–80 שאילתות. מעל 150 — יש בעיה. מעל 300 — יש תוסף שמתנהג רע.

Slow Query Log

ברמת השרת, מתעד כל שאילתה שחרגה מסף זמן. שימושי לאיתור בעיות שמופיעות רק בעומס.

שני מקורות שקטים לניפוח

wp_postmeta של WooCommerce

בחנויות, wp_postmeta היא בדרך כלל הטבלה הגדולה ביותר. כל הזמנה מייצרת עשרות שורות מטא, וכל מוצר עוד עשרות.

זה לגיטימי — אלה הנתונים שלכם. מה שלא לגיטימי הוא מטא של הזמנות שנמחקו, או של תוסף מעקב משלוחים שהוסר לפני שנתיים.

SELECT meta_key, COUNT(*) AS n FROM wp_postmeta
GROUP BY meta_key ORDER BY n DESC LIMIT 20;

מפתח שאתם לא מזהים, במאות אלפי שורות, הוא כמעט תמיד שארית.

הערה: WooCommerce המודרני מעביר הזמנות לטבלאות ייעודיות (HPOS) במקום ל-wp_posts. אם הפעלתם את זה, החלק הזה של הטבלה כבר קטן.

תגובות ספאם

תגובת ספאם שנחסמה עדיין יושבת ב-wp_comments, ועדיין מייצרת שורות ב-wp_commentmeta. אתר עם שנתיים של ספאם שלא נוקה יכול לגרור עשרות אלפי שורות מיותרות.

DELETE FROM wp_comments WHERE comment_approved = 'spam';
DELETE cm FROM wp_commentmeta cm
  LEFT JOIN wp_comments c ON c.comment_ID = cm.comment_id
  WHERE c.comment_ID IS NULL;

Akismet מוחק ספאם אוטומטית אחרי 15 יום, אבל רק אם הוא פעיל. אתר שהתוסף בוטל בו ממשיך לצבור.

מה קורה כשלא נוגעים בזה שנים

התסמינים מופיעים בסדר צפוי:

  1. לוח הבקרה נהיה איטי לפני האתר עצמו — הוא מבצע יותר שאילתות
  2. חיפוש פנימי מאט — הוא סורק את wp_posts המנופחת
  3. הגיבוי גדל וחורג ממגבלת זמן — ומתחיל להיכשל בשקט
  4. טעינת דף מאטה גם עם מטמון, כי הפינוי מייצר את הדף מחדש
  5. בעומס, הכל נופל בבת אחת — כי כל שאילתה עולה יותר

תחזוקה שוטפת

פעולהתדירות
בדיקת גודל autoloadרבעוני
ניקוי גרסאותחודשי (או אוטומטי)
ניקוי transients שפגוחודשי
בדיקת טבלאות יתומותאחרי הסרת תוסף
סקירת Query Monitorרבעוני

מה לא לעשות

אל תריצו OPTIMIZE TABLE על InnoDB באופן קבוע. ב-MyISAM זה היה שימושי. ב-InnoDB — מנוע ברירת המחדל היום — הפעולה בונה מחדש את הטבלה ונועלת אותה. באתר גדול זו השבתה, בתמורה לרווח זניח.

אל תסמכו על תוספי ניקוי בהרצה עיוורת. רובם טובים, אבל "ניקוי הכל" בלי גיבוי הוא הימור.

אל תמחקו מטא בלי לדעת מה זה. שדות מותאמים של WooCommerce יושבים ב-wp_postmeta, ומחיקה גורפת מוחקת נתוני הזמנות.

גיבוי לפני כל שאילתת מחיקה. תמיד.

מתי הבעיה היא לא מסד הנתונים

אם ניקיתם הכל וה-TTFB עדיין גבוה — הבעיה במקום אחר. בדקו לפי הסדר באופטימיזציית מהירות לוורדפרס, והתחילו מהתשתית: מסד נתונים על דיסק SATA משותף יהיה איטי גם כשהוא נקי לחלוטין.

שאלות נפוצות

האם תוספי ניקוי מסד נתונים בטוחים? רובם, כשמשתמשים בהם בזהירות. הסכנה היא באפשרויות "נקה הכל" שמוחקות גם דברים שתוסף פעיל צריך. גבו לפני, ובחרו מה למחוק במקום להריץ הכל.

כל כמה זמן לנקות? רבעונית מספיק לרוב האתרים. חנות פעילה — חודשית. הדבר החשוב יותר הוא למנוע הצטברות מלכתחילה: הגבלת גרסאות, Redis למטמון אובייקטים, וניקוי ספאם אוטומטי.

האם מסד נתונים גדול הוא בהכרח בעיה? לא. חנות עם 50,000 הזמנות תהיה גדולה, וזה תקין. הבעיה היא נתונים שאף אחד לא צריך — גרסאות, transients שפגו, ומטא של תוספים שהוסרו.

מה עושים אם הניקוי שבר משהו? משחזרים את הגיבוי שעשיתם לפני. זו הסיבה שהוא נדרש בכל פעם, גם כשהשאילתה נראית בטוחה.

שלוש נקודות לזכור

autoload הוא המקום להתחיל בו. שאילתה אחת אומרת לכם אם יש בעיה, והיא בדרך כלל נפתרת בהסרת שאריות של תוספים שכבר לא מותקנים.

גבו לפני כל מחיקה. כל שאילתת DELETE במאמר הזה בטוחה כשמבינים מה היא מוחקת, ובלתי הפיכה כשלא. הגיבוי הוא ההבדל.

מניעה זולה מניקוי. הגבלת גרסאות, Redis למטמון אובייקטים וסינון ספאם פעיל מונעים את רוב ההצטברות מראש — ואז אין מה לנקות.

איך נראה מסד נתונים בריא

שווה לדעת לאן מכוונים, כדי לזהות סטייה מוקדם.

מדדערך תקין באתר בינוני
גודל autoloadמתחת ל-800KB
שורות ב-wp_options300–1,500
שאילתות בדף הבית30–80
זמן שאילתות כוללמתחת ל-150ms
גרסאות לפוסטעד 5
טבלאות בסך הכל12 ליבה + 2–3 לכל תוסף משמעותי

חריגה באחד מהם אינה בהכרח בעיה — חנות גדולה תחרוג בכמה מהם באופן לגיטימי. מה שכן מעיד על בעיה הוא מגמה: אם מדדתם לפני חצי שנה ומאז הכל גדל פי שלושה בלי שהאתר גדל פי שלושה, משהו מצטבר.

לכן כדאי למדוד ולתעד פעם ברבעון. המספר המוחלט אומר מעט; השינוי אומר הרבה.


נכתב על ידי אביר, אחראי מידע ותוכן ב-CloudX. חבילות האחסון שלנו מריצות MariaDB על NVMe, ומטמון אובייקטים ב-Redis זמין בכל חבילה — מה שמונע את בעיית ה-transients מלכתחילה.