Make LEFT JOIN query more efficient

。_饼干妹妹 提交于 2020-01-16 18:12:48

问题


The following query with LEFT JOIN is drawing too much memory (~4GB), but the host only allows about 120MB for this process.

SELECT grades.grade, grades.evaluation_id, evaluations.evaluation_name, evaluations.value, evaluations.maximum FROM grades LEFT JOIN evaluations ON grades.evaluation_id = evaluations.evaluation_id WHERE grades.registrar_id = ?

Create table syntax for grades:

  CREATE TABLE `grades` (
  `grade_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `evaluation_id` int(10) unsigned DEFAULT NULL,
  `registrar_id` int(10) unsigned DEFAULT NULL,
  `grade` float unsigned DEFAULT NULL,
  `entry_date` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`grade_id`),
  KEY `registrarGrade_key` (`registrar_id`),
  KEY `evaluationKey` (`evaluation_id`),
  KEY `grades_id_index` (`grade_id`),
  KEY `eval_id_index` (`evaluation_id`),
  KEY `grade_index` (`grade`),
  CONSTRAINT `evaluationKey` FOREIGN KEY (`evaluation_id`) REFERENCES `evaluations` (`evaluation_id`),
  CONSTRAINT `registrarGrade_key` FOREIGN KEY (`registrar_id`) REFERENCES `registrar` (`reg_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1627 DEFAULT CHARSET=utf8;

evaluations table:

CREATE TABLE `evaluations` (
      `evaluation_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
      `instance_id` int(11) unsigned DEFAULT NULL,
      `evaluation_col` varchar(255) DEFAULT NULL,
      `evaluation_name` longtext,
      `evaluation_method` enum('class','email','online','lab') DEFAULT NULL,
      `evaluation_deadline` date DEFAULT NULL,
      `maximum` int(11) unsigned DEFAULT NULL,
      `value` float DEFAULT NULL,
      PRIMARY KEY (`evaluation_id`),
      KEY `instanceID_key` (`instance_id`),
      KEY `eval_name_index` (`evaluation_name`(3)),
      KEY `eval_method_index` (`evaluation_method`),
      KEY `eval_deadline_index` (`evaluation_deadline`),
      KEY `maximum` (`maximum`),
      KEY `value_index` (`value`),
      KEY `eval_id_index` (`evaluation_id`),
      CONSTRAINT `instanceID_key` FOREIGN KEY (`instance_id`) REFERENCES `course_instance` (`instance_id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=72 DEFAULT CHARSET=utf8;

The Php code to pull the data:

$sql = "SELECT grades.grade, grades.evaluation_id, evaluations.evaluation_name, evaluations.value, evaluations.maximum FROM grades LEFT JOIN evaluations ON grades.evaluation_id = evaluations.evaluation_id WHERE grades.registrar_id = ? AND YEAR(entry_date) = YEAR(CURDATE())";
                    $result = $mysqli->prepare($sql);
                    if($result === FALSE)
                        die($mysqli->error);
                    $result->bind_param('i',$reg_ids[$i]);
                    $result->execute();
                    $result->bind_result($grade, $eval_id, $evalname, $evalval, $max);
                    while($result->fetch()){ 

And the fatal error message

Is there a way to drastically reduce the memory load on this query?

Thanks!

  1. Curiously, changing the MySQL query did not change the amount of memory attempted to be allocated

回答1:


Please provide SHOW CREATE TABLE for both tables; I want to see if you have anything like these:

grades: INDEX(registration_id)

evaluations: PRIMARY KEY(evaluation_id)

Edit

You now have redundant indexes in both table -- probably because of my suggestion. That is, you already have both the indexes that would help with the query.

Since you have LONGTEXT and it is trying to allocate exactly 4GB, the max size of LONGTEXT, I guess that is the problem. Suggest you ALTER that column to be TEXT (64KB max) or MEDIUMTEXT (16MB max). I have not seen this behavior before in PHP, but then I rarely use anything bigger than TEXT.



来源:https://stackoverflow.com/questions/29191239/make-left-join-query-more-efficient

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!