mysql - 让LEFT JOIN查询更高效

标签 mysql performance database-performance processing-efficiency memory-efficient

以下使用 LEFT JOIN 的查询占用了太多内存 (~4GB),但主机仅允许此进程使用大约 120MB。

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 `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;

评估表:

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;

提取数据的Php代码:

$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()){ 

以及 fatal error 消息

enter image description here

有没有办法大幅减少该查询的内存负载?

谢谢!

  1. 奇怪的是,更改 MySQL 查询并没有改变尝试分配的内存量

最佳答案

请为两个表提供SHOW CREATE TABLE;我想看看你是否有这样的东西:

成绩:INDEX(registration_id)

评估:主键(evaluation_id)

编辑

现在两个表中都有冗余索引——可能是因为我的建议。也就是说,您已经拥有有助于查询的两个索引。

由于您有 LONGTEXT 并且它正在尝试分配恰好 4GB(LONGTEXT 的最大大小),我想这就是问题所在。建议您将该列更改为 TEXT(最大 64KB)或 MEDIUMTEXT(最大 16MB)。我以前没有在 PHP 中见过这种行为,但后来我很少使用比 TEXT 更大的东西。

关于mysql - 让LEFT JOIN查询更高效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29191239/

相关文章:

Mysql程序自增变量

android - : Intent. putExtra 或 SQLite 查询哪个更快?

MySQL 向大表中添加一列的性能

mysql - SQL 多对多关系

mysql - 这个怎么写? Mysql Result(动态查表)

php - 我错过了哪种技术来改善该网站的加载时间?不知所措

r - 从列表中选择多个元素以构建数据框的最快方法

数组的 JavaScript 性能

mysql - 在 C# 应用程序的 MySQL 数据库中的非常大的表中,简单的选择查询需要更多的时间

mysql - 选择一个 sql 字段并且不显示所选内容的特定单词