我正在将数据库从 Mysql 8.0.23 迁移到 MariaDB 11.3.2,我意识到 MariaDB 中的某些查询比 Mysql 中需要更长的时间。这是相同的查询和相同的数据库结构。在 MariaDB 中,我需要 3.5 秒才能得到响应,而在 mysql 服务器中只需 0.8 秒。我执行
Explain
和 Analyze
命令,我发现运行过程是不同的。因为我将继续查看评估了多少行,并创建一些索引,但我不认为评估的行是相似的。如何优化 mariaDB 数据库?您对如何继续优化数据库有任何提示吗?预先感谢您!
致以诚挚的问候,
保罗
有疑问:
select `q`.*, EXISTS (
SELECT `qe`.* FROM `questions` `qe`
CROSS JOIN `companies_has_users` `cu` ON cu.company_id = 160
LEFT JOIN `answer_groups` `ag` ON ag.question_id = qe.id AND ag.archived = 0
LEFT JOIN `answer_fields` `af` ON af.answer_group_id = ag.id AND af.archived = 0
LEFT JOIN `answers` `a` ON a.answer_field_id = af.id AND a.is_answered = 1 AND a.user_id = cu.user_id AND a.questionnaire_id = 228
LEFT JOIN `answers` `a_2` ON a_2.answer_field_id = af.id AND a_2.is_default = 1
LEFT JOIN `answer_fields` `af_2` ON af_2.id = a.answer_field_id AND af_2.archived = 0
LEFT JOIN `answer_fields` `af_3` ON af_3.id = a_2.answer_field_id AND af_3.archived = 0
LEFT JOIN `questions_has_user_files` `quf` ON quf.question_id = qe.id AND quf.company_id = 160
LEFT JOIN `questionnaires_has_questions` `qhq` ON qhq.question_id = qe.id
WHERE ((`qhq`.`questionnaire_id` = 228) OR (`qhq`.`questionnaire_id` = 149)) AND (`qe`.`archived`=FALSE) AND (qe.id = q.id) AND (`a`.`id` IS NOT NULL)) AS `count_answers`,
EXISTS (SELECT `qe`.* FROM `questions` `qe`
CROSS JOIN `companies_has_users` `cu` ON cu.company_id = 160
LEFT JOIN `answer_groups` `ag` ON ag.question_id = qe.id AND ag.archived = 0
LEFT JOIN `answer_fields` `af` ON af.answer_group_id = ag.id AND af.archived = 0
LEFT JOIN `answers` `a` ON a.answer_field_id = af.id AND a.is_answered = 1 AND a.user_id = cu.user_id AND a.questionnaire_id = 228
LEFT JOIN `answers` `a_2` ON a_2.answer_field_id = af.id AND a_2.is_default = 1
LEFT JOIN `answer_fields` `af_2` ON af_2.id = a.answer_field_id AND af_2.archived = 0
LEFT JOIN `answer_fields` `af_3` ON af_3.id = a_2.answer_field_id AND af_3.archived = 0
LEFT JOIN `questions_has_user_files` `quf` ON quf.question_id = qe.id AND quf.company_id = 160
LEFT JOIN `questionnaires_has_questions` `qhq` ON qhq.question_id = qe.id
WHERE ((`qhq`.`questionnaire_id` = 228) OR (`qhq`.`questionnaire_id` = 149)) AND (`qe`.`archived`=FALSE) AND (qe.id = q.id) AND (`a_2`.`id` IS NOT NULL)) AS `count_default_answers`,
EXISTS (SELECT `qe`.* FROM `questions` `qe`
CROSS JOIN `companies_has_users` `cu` ON cu.company_id = 160
LEFT JOIN `answer_groups` `ag` ON ag.question_id = qe.id AND ag.archived = 0
LEFT JOIN `answer_fields` `af` ON af.answer_group_id = ag.id AND af.archived = 0
LEFT JOIN `answers` `a` ON a.answer_field_id = af.id AND a.is_answered = 1 AND a.user_id = cu.user_id AND a.questionnaire_id = 228
LEFT JOIN `answers` `a_2` ON a_2.answer_field_id = af.id AND a_2.is_default = 1
LEFT JOIN `answer_fields` `af_2` ON af_2.id = a.answer_field_id AND af_2.archived = 0
LEFT JOIN `answer_fields` `af_3` ON af_3.id = a_2.answer_field_id AND af_3.archived = 0
LEFT JOIN `questions_has_user_files` `quf` ON quf.question_id = qe.id AND quf.company_id = 160
LEFT JOIN `questionnaires_has_questions` `qhq` ON qhq.question_id = qe.id
WHERE ((`qhq`.`questionnaire_id` = 228) OR (`qhq`.`questionnaire_id` = 149)) AND (`qe`.`archived`=FALSE) AND (qe.id = q.id) AND ((`af_2`.`user_upload_enabled`=2) OR (`af_3`.`user_upload_enabled`=2))) AS `user_upload_enabled`,
EXISTS (SELECT `qe`.* FROM `questions` `qe`
CROSS JOIN `companies_has_users` `cu` ON cu.company_id = 160
LEFT JOIN `answer_groups` `ag` ON ag.question_id = qe.id AND ag.archived = 0
LEFT JOIN `answer_fields` `af` ON af.answer_group_id = ag.id AND af.archived = 0
LEFT JOIN `answers` `a` ON a.answer_field_id = af.id AND a.is_answered = 1 AND a.user_id = cu.user_id AND a.questionnaire_id = 228
LEFT JOIN `answers` `a_2` ON a_2.answer_field_id = af.id AND a_2.is_default = 1
LEFT JOIN `answer_fields` `af_2` ON af_2.id = a.answer_field_id AND af_2.archived = 0
LEFT JOIN `answer_fields` `af_3` ON af_3.id = a_2.answer_field_id AND af_3.archived = 0
LEFT JOIN `questions_has_user_files` `quf` ON quf.question_id = qe.id AND quf.company_id = 160
LEFT JOIN `questionnaires_has_questions` `qhq` ON qhq.question_id = qe.id
WHERE ((`qhq`.`questionnaire_id` = 228) OR (`qhq`.`questionnaire_id` = 149)) AND (`qe`.`archived`=FALSE) AND (qe.id = q.id) AND ((`quf`.`file_id` IS NOT NULL) AND (`quf`.`questionnaire_id`=228))) AS `has_user_file_id` FROM `questions` `q`
LEFT JOIN `questionnaires_has_questions` `qhq` ON qhq.question_id = q.id
WHERE ((`qhq`.`questionnaire_id` = 228) OR (`qhq`.`questionnaire_id` = 149)) AND (`q`.`archived`=FALSE)
GROUP BY `q`.`id` ORDER BY `count_answers` DESC, `count_default_answers` DESC
我在两台服务器中执行解释,以了解如果我找到需要优化的内容,我会得到:
更新 23.06.2024:我添加了两个解释的图像。并删除了 Markdown 中的表格。
我得出的结论是,除了
WHERE
子句之外,子查询都是相同的。
通常的措辞只是
EXPLAIN SELECT 1 ...
(而不是*
)。 (这不会影响性能。)
这 4 个子查询似乎在做几乎相同的事情;你能以某种方式加入其中常见内容的单个副本吗?
WHERE 似乎有一个共同点:
WHERE ((`qhq`.`questionnaire_id` = 228) OR (`qhq`.`questionnaire_id` = 149)) AND (`qe`.`archived`=FALSE) AND (qe.id = q.id)
OR
成本高昂。 做 1 个副本而不是 4 个副本可能会加速。
并且有所不同
AND (`a`.`id` IS NOT NULL) -- `count_answers`,
AND(`a_2`.`id` IS NOT NULL) ) --`count_default_answers`,
AND ((`af_2`.`user_upload_enabled`=2) OR (`af_3`.`user_upload_enabled`=2)) --`user_upload_enabled`,
AND ((`quf`.`file_id` IS NOT NULL) AND (`quf`.`questionnaire_id`=228)) -- `has_user_file_id`