我陷入了这样一个境地:我有数百万条记录,并且需要不同的连接来实现相同的记录。订单条款也有一些棘手的部分。如果我不应用任何排序,我的查询会执行快速结果。但在应用 order 子句时,需要花费太多时间才能得到结果。
如果没有 Order 子句,则会导致 5-6 秒。
应用订单条款时,结果为 40-45 秒
SELECT forms_values.id, CASE WHEN forms_values.appointment_type = 2 AND user_patient_assinged_to_doctor.start_time IS NOT NULL THEN CASE WHEN patient_responded_tags_logs.tag_set_at IS NOT NULL THEN CASE WHEN UNIX_TIMESTAMP( CONVERT_TZ( patient_responded_tags_logs.tag_set_at, "+00:00", "-06:00" ) ) > UNIX_TIMESTAMP( CONVERT_TZ( STR_TO_DATE( CONCAT( user_patient_assinged_to_doctor.date, " ", user_patient_assinged_to_doctor.start_time ), "%Y-%m-%d %h:%i %p" ), "+00:00", "-06:00" ) ) THEN UNIX_TIMESTAMP( CONVERT_TZ( patient_responded_tags_logs.tag_set_at, "+00:00", "-06:00" ) ) ELSE UNIX_TIMESTAMP( CONVERT_TZ( STR_TO_DATE( CONCAT( user_patient_assinged_to_doctor.date, " ", user_patient_assinged_to_doctor.start_time ), "%Y-%m-%d %h:%i %p" ), "+00:00", "-06:00" ) ) END ELSE UNIX_TIMESTAMP( CONVERT_TZ( STR_TO_DATE( CONCAT( user_patient_assinged_to_doctor.date, " ", user_patient_assinged_to_doctor.start_time ), "%Y-%m-%d %h:%i %p" ), "+00:00", "-06:00" ) ) END ELSE CASE WHEN patient_responded_tags_logs.tag_set_at IS NOT NULL THEN CASE WHEN UNIX_TIMESTAMP( CONVERT_TZ( patient_responded_tags_logs.tag_set_at, "+00:00", "-06:00" ) ) > UNIX_TIMESTAMP(forms_values.created_at) THEN UNIX_TIMESTAMP( CONVERT_TZ( patient_responded_tags_logs.tag_set_at, "+00:00", "-06:00" ) ) ELSE UNIX_TIMESTAMP(forms_values.created_at) END ELSE UNIX_TIMESTAMP(forms_values.created_at) END END AS "consultation_date_time_ordering", CASE WHEN forms_values.appointment_type = 2 AND user_patient_assinged_to_doctor.start_time IS NOT NULL THEN UNIX_TIMESTAMP( CONVERT_TZ( STR_TO_DATE( CONCAT( user_patient_assinged_to_doctor.date, " ", user_patient_assinged_to_doctor.start_time ), "%Y-%m-%d %h:%i %p" ), "+00:00", "-06:00" ) ) ELSE UNIX_TIMESTAMP(forms_values.created_at) END AS "consultation_date_time" , CASE WHEN forms_values.is_postpone = '1' OR forms_values.is_completed = '8' THEN CASE WHEN UNIX_TIMESTAMP( CONVERT_TZ( STR_TO_DATE( CONCAT(UTC_DATE(), ' ', UTC_TIME()), '%Y-%m-%d %h:%i:%s' ), '+00:00', '-06:00' ) ) < UNIX_TIMESTAMP( my_list_postpone.postponed_date ) THEN 0 ELSE 1 END ELSE 1 END AS "postponed_consultation_ordering" FROM `forms_values` LEFT JOIN `forms_values_completed_status_details` ON `forms_values_completed_status_details`.`form_value_id` = `forms_values`.`id` /*INNER JOIN `users` ON `users`.`id` = `forms_values`.`patient_id` LEFT JOIN `users` AS `doctors` ON `doctors`.`id` = `forms_values`.`doctor_id`*/ LEFT JOIN `user_patient_assinged_to_doctor` ON `user_patient_assinged_to_doctor`.`form_value_id` = `forms_values`.`id` INNER JOIN `states_countries` ON `forms_values`.`state` = `states_countries`.`id` LEFT JOIN `user_payment_history` ON `user_payment_history`.`form_value_id` = `forms_values`.`id` LEFT JOIN `emailed_tags_logs` ON `emailed_tags_logs`.`form_value_id` = `forms_values`.`id` AND `emailed_tags_logs`.`id` = (SELECT emailed_tags_logs.id FROM emailed_tags_logs WHERE emailed_tags_logs.form_value_id = forms_values.id AND emailed_tags_logs.id = (SELECT emailed_tags_logs1.id AS emtid FROM emailed_tags_logs AS emailed_tags_logs1 WHERE emailed_tags_logs1.form_value_id = forms_values.id ORDER BY emailed_tags_logs1.created_at DESC LIMIT 1) AND emailed_tags_logs.status IN (1, 3) AND emailed_tags_logs.is_pt_responded = "0" ORDER BY emailed_tags_logs.created_at DESC LIMIT 1) LEFT JOIN `my_list_assign_doctor` ON `my_list_assign_doctor`.`form_value_id` = `forms_values`.`id` AND `my_list_assign_doctor`.`id` = (SELECT my_list_assign_doctor.id FROM my_list_assign_doctor WHERE my_list_assign_doctor.form_value_id = forms_values.id AND my_list_assign_doctor.status IN (1, 2) AND my_list_assign_doctor.prior_type = "others" ORDER BY my_list_assign_doctor.created_at DESC LIMIT 1) LEFT JOIN `my_list_assign_doctor` AS `my_list_postpone` ON `my_list_postpone`.`form_value_id` = `forms_values`.`id` AND `forms_values`.`is_postpone` IN ('1', '2') AND `my_list_postpone`.`id` = (SELECT my_list_assign_doctor.id FROM my_list_assign_doctor WHERE my_list_assign_doctor.form_value_id = forms_values.id AND my_list_assign_doctor.prior_type = "postpone" ORDER BY my_list_assign_doctor.created_at DESC LIMIT 1) LEFT JOIN `users` AS `partner` ON `user_payment_history`.`std_partner_id` = `partner`.`id` LEFT JOIN `patient_responded_tags_logs` ON `patient_responded_tags_logs`.`form_value_id` = `forms_values`.`id` AND `patient_responded_tags_logs`.`status` = '1' LEFT JOIN `user_subscriptions` ON `user_subscriptions`.`user_payment_history_id` = `user_payment_history`.`id` AND `user_payment_history`.`form_value_id` = `forms_values`.`id` ORDER BY postponed_consultation_ordering DESC, `consultation_date_time` DESC LIMIT 10 OFFSET 0
注意:所有联接都很重要,出于某些考虑,字段已从选择查询中删除。
解释摘要
问题出在 LIMIT 和 ORDER BY 的组合上。
如果没有 ORDER BY,一旦选择了前十个随机行,查询就会停止。按照 order by 查询必须收集所有可能的行,然后按顺序对它们进行排序,然后仅返回前 10 行。
考虑到“postponed_consultation_datetime”是一个计算字段,确实没有办法让它更快。