Очень медленный результат при использовании условия WHERE и ORDER BY в MYSQL Query - PullRequest
0 голосов
/ 25 марта 2019

Я столкнулся с проблемой очень медленного результата.

Я делюсь структурой таблицы так же, как и результаты.

если у вас есть предложения, пожалуйста, обновите их в ближайшее время, если это возможно.

=============================================== ================== Структура таблицы - https://www.phpmyadmin.net/ - - Хост: localhost: 3306 - Время генерации: 25 марта 2019 года в 11:48 - Версия сервера: 5.5.61-cll - Версия PHP: 7.2.7

SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET AUTOCOMMIT = 0;
START TRANSACTION;
SET time_zone = "+00:00";

--
-- Database: `energe3c_lms`
--

-- --------------------------------------------------------

--
-- Table structure for table `user_material`
--

CREATE TABLE `user_material` (
  `id` int(11) NOT NULL,
  `user_course_id` int(11) NOT NULL,
  `user_id` int(11) NOT NULL,
  `material_id` int(11) NOT NULL,
  `attempt` int(11) NOT NULL,
  `another_attempt` tinyint(1) DEFAULT '0',
  `status` varchar(255) DEFAULT NULL,
  `complete` tinyint(1) DEFAULT NULL,
  `percent` float DEFAULT '0',
  `time` varchar(255) DEFAULT NULL,
  `marking_time` varchar(255) DEFAULT NULL,
  `marked_by` int(11) DEFAULT NULL,
  `feedback` text,
  `submitted_date` datetime DEFAULT NULL,
  `marking_date` datetime DEFAULT NULL,
  `created` datetime DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

--
-- Indexes for dumped tables
--

--
-- Indexes for table `user_material`
--
ALTER TABLE `user_material`
  ADD PRIMARY KEY (`id`),
  ADD KEY `user_material-user` (`user_id`),
  ADD KEY `user_material-material` (`material_id`),
  ADD KEY `user_material-marking-user` (`marked_by`),
  ADD KEY `user_course-user_material` (`user_course_id`);

--
-- AUTO_INCREMENT for dumped tables
--

--
-- AUTO_INCREMENT for table `user_material`
--
ALTER TABLE `user_material`
  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;

--
-- Constraints for dumped tables
--

--
-- Constraints for table `user_material`
--
ALTER TABLE `user_material`
  ADD CONSTRAINT `user_course-user_material` FOREIGN KEY     (`user_course_id`) REFERENCES `user_course` (`id`) ON DELETE CASCADE ON     UPDATE CASCADE,
  ADD CONSTRAINT `user_material-marking-user` FOREIGN KEY (`marked_by`) REFERENCES `user` (`id`) ON DELETE SET NULL ON UPDATE CASCADE,
  ADD CONSTRAINT `user_material-material` FOREIGN KEY (`material_id`) REFERENCES `material` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  ADD CONSTRAINT `user_material-user` FOREIGN KEY (`user_id`)     REFERENCES `user` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;

COMMIT;

Показаны строки 0 - 24 (всего 25586268, запрос занял 0,0007 секунды.)

ВЫБРАТЬ * ИЗ user_material

=============================================== ==================

Отображение строк 0 - 24 (всего 77, запрос занял 22,9434 секунды.)

SELECT * FROM user_material, где status = 'submit'

=============================================== ==================

Показаны строки 0 - 24 (всего 34026300, запрос занял 24,4978 секунд.) [submit_date: ... - ...]

ВЫБРАТЬ * ОТ user_material ЗАКАЗАТЬ НА ОТДЕЛЕННУЮ ДАТУ ASC

=============================================== ==================

Если у вас есть предложения, пожалуйста, сообщите мне.

Я использую этот запрос в yii2 framework

Ответы [ 3 ]

0 голосов
/ 25 марта 2019

В дополнение к рекомендации @Gordon Linoff, вы должны рассмотреть вопрос нормализации вашей таблицы, чтобы сделать SQL более эффективным. Используйте очень короткий код или int для status_id и сохраните уникальный список кодов состояния и описания в справочной таблице. Затем просто присоединитесь к таблице поиска в вашем SQL. См. статью для подробного объяснения нормализации.

Я также рекомендую изменить имя столбца или тип данных для столбца time, поскольку это не имеет смысла. Какое значение времени требует 255 символов?

Если вас беспокоит производительность, то первое, на что вы должны обратить внимание, - это удалить ненужные байты, сортировки и фильтры из вашего запроса. Этот подход имеет дело с большинством проблем производительности. То, как вы присоединяетесь к столам, также важно. По мере увеличения объема и сложности данных настройка также становится все более сложной.

Знакомство EXPLAIN поможет вашим усилиям. Обратитесь к ОБЪЯСНИТЕ документации для получения дополнительной информации.

-- Create your lookup table first
CREATE TABLE `material_status` (
  `id` int(11) NOT NULL,
  `status` varchar(255) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

ALTER TABLE `material_status`
  ADD PRIMARY KEY (`id`),

ALTER TABLE `material_status`
  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;

-- Then create your user_material table
CREATE TABLE `user_material` (
  `id` int(11) NOT NULL,
  `user_course_id` int(11) NOT NULL,
  `user_id` int(11) NOT NULL,
  `material_id` int(11) NOT NULL,
  `attempt` int(11) NOT NULL,
  `another_attempt` tinyint(1) DEFAULT '0',
  `status_id` int(11) DEFAULT NULL,
  `complete` tinyint(1) DEFAULT NULL,
  `percent` float DEFAULT '0',
  `time` varchar(255) DEFAULT NULL,
  `marking_time` varchar(255) DEFAULT NULL,
  `marked_by` int(11) DEFAULT NULL,
  `feedback` text,
  `submitted_date` datetime DEFAULT NULL,
  `marking_date` datetime DEFAULT NULL,
  `created` datetime DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- Create your extra index here
CREATE INDEX ix-submitted_date ON user_material(submitted_date);

-- Add the status to the keys and constraints
ALTER TABLE `user_material`
  ADD PRIMARY KEY (`id`),
  ADD KEY `user_material-user` (`user_id`),
  ADD KEY `user_material-material` (`material_id`),
  ADD KEY `user_material-marking-user` (`marked_by`),
  ADD KEY `user_course-user_material` (`user_course_id`),
  ADD KEY `user_material-status` (`status_id`);

ALTER TABLE `user_material`
  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;

ALTER TABLE `user_material`
  ADD CONSTRAINT `user_course-user_material` FOREIGN KEY (`user_course_id`) REFERENCES `user_course` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  ADD CONSTRAINT `user_material-marking-user` FOREIGN KEY (`marked_by`) REFERENCES `user` (`id`) ON DELETE SET NULL ON UPDATE CASCADE,
  ADD CONSTRAINT `user_material-material` FOREIGN KEY (`material_id`) REFERENCES `material` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  ADD CONSTRAINT `user_material-user` FOREIGN KEY (`user_id`)     REFERENCES `user` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  ADD CONSTRAINT `user_material-status` FOREIGN KEY (`status_id`) REFERENCES `material_status` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;

Теперь запросы будут выглядеть так:

SELECT
um.id,
um.user_course_id,
um.user_id,
um.material_id,
um.attempt,
um.another_attempt,
ms.status,
um.complete,
um.percent,
um.time,
um.marking_time,
um.marked_by,
um.feedback,
um.submitted_date,
um.marking_date,
um.created
FROM user_material um
INNER JOIN material_status ms on ms.id = um.status_id
WHERE ms.status = 'submitted';

SELECT
um.id,
um.user_course_id,
um.user_id,
um.material_id,
um.attempt,
um.another_attempt,
ms.status,
um.complete,
um.percent,
um.time,
um.marking_time,
um.marked_by,
um.feedback,
um.submitted_date,
um.marking_date,
um.created
FROM user_material um
INNER JOIN material_status ms on ms.id = um.status_id
ORDER BY um.submitted_date ASC;
0 голосов
/ 25 марта 2019

Пожалуйста, попробуйте это.

SELECT
um.id,
um.user_course_id,
um.user_id,
um.material_id,
um.attempt,
um.another_attempt,
ms.status,
um.complete,
um.percent,
um.time,
um.marking_time,
um.marked_by,
um.feedback,
um.submitted_date,
um.marking_date,
um.created
FROM user_material um
INNER JOIN material_status ms on ms.id = um.status_id
AND ms.status = 'submitted'; 

А также создать индексацию по полю и порядку.

0 голосов
/ 25 марта 2019

Для этого запроса:

SELECT *
FROM user_material 
WHERE status = 'submitted';

Вы хотите индекс на user_material(status).

Для этого запроса:

SELECT *
FROM user_material
ORDER BY submitted_date ASC

Вы хотите индекс на user_material(submitted_date).

В обоих этих случаях дополнительные столбцы могут быть в индексе после столбца, указанного в качестве первого столбца. Я не вижу этих индексов в вашей схеме.

...