שיפור ביצועים של אלפי inserts בשניה בMYSQL
-
אולי זה יעזור?
זה המבנה של הטבלהCREATE TABLE `answers` ( `id` INT(10) NOT NULL AUTO_INCREMENT, `room` INT(11) NULL DEFAULT NULL, `questionId` INT(11) NULL DEFAULT NULL, `answerId` INT(11) NULL DEFAULT NULL, `answerText` TEXT NULL DEFAULT NULL, PRIMARY KEY (`id`));
הסטטוס של הטבלה
mysql> show table status WHERE Name = 'answers'; +---------+--------+---------+------------+-------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+-------------+------------+--------------------+----------+----------------+---------+ | Name | Engine | Version | Row_format | Rows | Avg_row_length | Data_length | Max_data_length | Index_length | Data_free | Auto_increment | Create_time | Update_time | Check_time | Collation | Checksum | Create_options | Comment | +---------+--------+---------+------------+-------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+-------------+------------+--------------------+----------+----------------+---------+ | answers | InnoDB | 10 | Compact | 45984 | 99 | 4554752 | 0 | 0 | 4194304 | 96598 | 2020-04-26 06:17:37 | NULL | NULL | utf8mb4_unicode_ci | NULL | | | +---------+--------+---------+------------+-------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+-------------+------------+--------------------+----------+----------------+---------+
-
עכשיו שמתי לב שטעיתי
מדובר בטבלה אחרתCREATE TABLE `points` ( `id` INT(10) NOT NULL AUTO_INCREMENT, `room` INT(11) NULL DEFAULT NULL, `user` VARCHAR(20) NULL DEFAULT NULL, `questionId` INT(11) NULL DEFAULT NULL, `points` INT(11) NULL DEFAULT NULL, `time` INT(64) NULL DEFAULT NULL, `grup` VARCHAR(64) NULL DEFAULT NULL, `answerId` INT(11) NULL DEFAULT NULL, PRIMARY KEY (`id`)"
הסטטוס שלה הוא
mysql> show table status WHERE Name = 'points'; +--------+--------+---------+------------+--------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+-------------+------------+--------------------+----------+----------------+---------+ | Name | Engine | Version | Row_format | Rows | Avg_row_length | Data_length | Max_data_length | Index_length | Data_free | Auto_increment | Create_time | Update_time | Check_time | Collation | Checksum | Create_options | Comment | +--------+--------+---------+------------+--------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+-------------+------------+--------------------+----------+----------------+---------+ | points | InnoDB | 10 | Compact | 553311 | 82 | 45678592 | 0 | 0 | 4194304 | 1599099 | 2020-08-11 21:53:07 | NULL | NULL | utf8mb4_unicode_ci | NULL | | | +--------+--------+---------+------------+--------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+-------------+------------+--------------------+----------+----------------+---------+
והשאילתא נראת כך
INSERT INTO `points` (`room`,`user`,`questionId`,`points`,`time`,`grup`,`answerId`) VALUES (?,?,?,?,?,?,? )", room, user, questionId, points, time, grup, answerId
קצת יותר גדול
אבל לא נראה לי שאמור להפריע כל כך -
@nigun אני גם לא חושב שזה אמור כל כך להפריע, אבל לפי התאור הראשוני גם מבוצעות שאילתות SELECT ו-INSERT בו זמנית על טבלה זו, ועם חצי מליון שורות אני חושב שכדאי מאוד היה לנרמל את הנתונים עוד יותר, למשל
- כדאי להפוך את כל השדות של ה-VARCHAR ל-INT.
user => UserId
grup => groupId
וליצור טבלאות עבור Groups ו- Users. - לחשוב טוב האם כל השדות האלו הכרחיים לשמירה עבור כל תשובה?
- אם time הוא רק חותמת זמן, הייתי משאיר זאת לבסיס הנתונים לקבוע ערך ברירת מחדל עבור השדה (=לזמן הנוכחי) ומסיר אותו מה-INSERT.
- כמה שתקטין יותר את הטבלה המהירות תהיה כנראה טובה יותר. יש לך 4 גורמים שאחראים על המהירות הכללית: מעבד, זיכרון, דיסק ורשת. תבדוק את כולם. אם למשל כל הנתונים לא נטענים לזיכרון בבת אחת, הDB יבצע קאשינג והמהירות תרד פלאים בשעות העומס...
- אני נזכר שכבר היתה לך איזו בעיה כזו בעבר, וה Execution Plan של ה-DB לא היתה אופטימלית. לפי זכרוני השתמשת בגירסא מיושנת של MySQL, ואולי כדאי לבצע שדרוג.
- כדאי להפוך את כל השדות של ה-VARCHAR ל-INT.
-
עכשיו היה לי כ650 משתמשים על המערכת
וזה אולי נותן קצת יותר תמונה (נראה לי שהנתונים של DO יותר מדוייקים)
כפי שרואים בתמונה אין כל כל הרבה inserts בו זמנית, אלא fetchs
מה זה fetch? ולמה יש לי כל כך הרבה בשניה?
עריכה: אני מבין שזה כתוב השורות במסד נתונים מדפיס בSELECT
אז כנראה שזה לא בעיה.
בכל אופן נראה שהמסד נתונים של DO מתמודד עם זה יפה (הCPU ממש נמוך)
אולי בגלל שהוא משתמש בגירסה 8.0?