MySQL Просмотр проблемы производительности с совокупным запросом - PullRequest
2 голосов
/ 30 января 2020

Я использую mysql версия 5.6.47. У меня есть следующая таблица оценок учеников:

CREATE TABLE `studentmarks` (
  `ID` int(11) NOT NULL AUTO_INCREMENT,
  `StudentID` int(11) NOT NULL,
  `subjectName` varchar(255) DEFAULT NULL,
  `MARKS` int(11) NOT NULL,
  PRIMARY KEY (`ID`),
  KEY `idx_studentmarks_StudentID` (`StudentID`)
);

и я создал представление на столе:

CREATE OR REPLACE VIEW `vw_student_marks` AS
    SELECT 
        `s1`.`StudentID` AS `StudentID`,
        `s1`.`subjectName` AS `subjectName`,
        `s1`.`MARKS` AS `marks`,
        (SELECT 
                SUM(`s2`.`MARKS`)
            FROM
                `studentmarks` `s2`
            WHERE
                (`s2`.`StudentID` = `s1`.`StudentID`)) AS `totalMarks`
    FROM
        `studentmarks` `s1`;

При тестировании с примерно 20К строками наблюдается заметная разница в производительности работает SELECT query против SELECT * FROM VIEW. Запрос на выборку показывает оптимизированный план выполнения с одним полным сканированием таблицы, в то время как для просмотра есть два полных сканирования таблицы.

Статистика запросов (измеряется MySQL Workbench):

SELECT QUERY

Timing: 0:00:0.07677120 (as measured by the server)

Rows Examined: 108285

ВЫБРАТЬ ИЗ ЗАПРОСА ПРОСМОТРА:

Timing: 0:00:1.6082441 (as measured by the server)

Rows Examined: 2985730

В чем причина такой разницы в производительности?

Планы выполнения запросов: https://i.stack.imgur.com/noOxI.jpg

ОБНОВЛЕНИЕ: Я протестировал с MySQL версия 8.0.19, такая же проблема возникает

Ответы [ 2 ]

1 голос
/ 30 января 2020

MySQL должен использовать алгоритм TEMPTABLE для представления в этом случае (агрегатные функции). Это может быть причиной разницы.

Для более подробной информации вы можете обратиться https://dev.mysql.com/doc/refman/5.6/en/view-algorithms.html.

Если алгоритм MERGE не может быть использован, временный Таблица должна быть использована вместо. MERGE нельзя использовать, если представление содержит любую из следующих конструкций:

Агрегатные функции (SUM (), MIN (), MAX (), COUNT () и т. Д.)

DISTINCT

GROUP BY

HAVING

LIMIT

UNION или UNION ALL

Подзапрос в списке выбора

Назначение к пользовательским переменным

Относится только к буквальным значениям (в данном случае нет базовой таблицы)

0 голосов
/ 30 января 2020

FWIW, я написал бы это, используя некоррелированный подзапрос (но я согласен, что это не обязательно улучшит производительность) - и вообще отказался бы от идеи использования представления ...

SELECT s1.StudentID
     , s1.subjectName
     , s1.MARKS
     , s2.totalmarks
  FROM studentmarks s1
  JOIN
     ( SELECT studentid
            , SUM(s2.MARKS) totalmarks
         FROM studentmarks
        GROUP 
           BY studentid
     ) s2
    ON s2.studentid = s1.studentid;
...