【问题标题】:MySQL query slows down computerMySQL查询减慢计算机速度
【发布时间】:2020-11-18 19:06:31
【问题描述】:

我正在对我的 MySQL 数据库进行查询。查询最多需要 5 分钟:

SELECT
  COUNT(*) as tasks,
  tasks.owner,
  ROUND(AVG(TIMESTAMPDIFF(day, tasks.created_on, tasks.last_modified)), 0) as avg_time
FROM
  tasks 
LEFT JOIN
  objects ON objects.number = tasks.relationship
WHERE
  tasks.status != "Potential"
GROUP BY
  tasks.owner
ORDER BY avg_time DESC
LIMIT 10

tasks 表有大约 60,000 行。 我的 MacBook Pro 的mysqld 进程占用了整个 CPU,我的粉丝也出现了。我的查询是坏的还是 MySQL 有 60,000 行? 我要加入的 objects 表有大约 15,000 行。

这里是创建语句:

CREATE TABLE `tasks` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `complete` varchar(255) DEFAULT NULL,
  `completed_by` varchar(255) DEFAULT NULL,
  `owner` varchar(255) DEFAULT NULL,
  `delegate` varchar(255) DEFAULT NULL,
  `created_on` timestamp NULL DEFAULT NULL,
  `task_name` varchar(255) DEFAULT NULL,
  `last_modified` timestamp NULL DEFAULT NULL,
  `reassigned` varchar(255) DEFAULT NULL,
  `role` varchar(255) DEFAULT NULL,
  `status` varchar(255) DEFAULT NULL,
  `relationship` varchar(255) DEFAULT NULL,
  `unique_id` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=59444 DEFAULT CHARSET=utf8
CREATE TABLE `objects` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  `number` varchar(255) DEFAULT NULL,
  `context` varchar(255) DEFAULT NULL,
  `owner` varchar(255) DEFAULT NULL,
  `route` varchar(255) DEFAULT NULL,
  `created_on` timestamp NULL DEFAULT NULL,
  `last_modified` timestamp NULL DEFAULT NULL,
  `status` varchar(255) DEFAULT NULL,
  `project` varchar(255) DEFAULT NULL,
  `relationship` varchar(255) DEFAULT NULL,
  `unique_id` varchar(255) DEFAULT NULL,
  `type` varchar(255) DEFAULT NULL,
  `description` text,
  `proposed_solution` text,
  `region_of_approval` varchar(255) DEFAULT NULL,
  `requested_by` varchar(255) DEFAULT NULL,
  `customer` varchar(255) DEFAULT NULL,
  `promotion_state` varchar(255) DEFAULT NULL,
  `priority` varchar(255) DEFAULT NULL,
  `business` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `number` (`number`)
) ENGINE=InnoDB AUTO_INCREMENT=16700 DEFAULT CHARSET=utf8

这是objects 的一些示例数据:

"id","name","number","context","owner","route","created_on","last_modified","status","project","relationship","unique_id","type","description","proposed_solution","region_of_approval","requested_by","customer","promotion_state","priority","business"
1,"NEW ARTICLE","CN0345928","Library","Max","Change Released","2020-11-17 06:13:00","2020-11-17 06:13:00","Released",NULL,"CR86030","2516967988","Change Notice","",NULL,"Americas-Europe",NULL,"","Released",NULL,"EU"
2,"Set Hose to Service Only","CN0345931","Library","Mo","Set to Service Only","2020-11-17 06:37:00","2020-11-17 06:37:00","Released",NULL,"CR86171","2516984806","Change Notice","",NULL,"Americas-Europe",NULL,"","Service Only",NULL,"EU"
3,"NEW MEASURING DEVICE","CN0344110","Library","Max","Promote to Release","2020-10-19 08:24:00","2020-10-19 08:39:00","Released",NULL,"CR85808","2493544772","Change Notice","",NULL,"Europe",NULL,"","Released",NULL,"EU"

对于tasks

"id","complete","completed_by","owner","delegate","created_on","task_name","last_modified","reassigned","role","status","relationship","unique_id"
1,"No","member",NULL,"","2008-08-27 20:28:00","Test of creating a parent part","2008-08-27 20:28:00","No","Assignee","Potential",11377,"3A67054501"
2,"Yes","member",NULL,"","2008-09-02 16:02:00","create a bom","2008-09-02 16:11:00","No","Assignee","Completed",11496,"3A67490902"
3,"Yes","member",NULL,"","2008-09-02 16:12:00","create a bom","2008-09-02 16:17:00","No","Reviewer","Completed",11496,"3A67491252"

【问题讨论】:

  • 为两个表提供 CREATE TABLE。
  • mysql 的数字很小。请添加您的表定义(我们需要查看有哪些索引)和执行计划。
  • tasks.relationship 是否已编入索引?如果是这样,objects.number 是该索引的外键吗?
  • 当我说样式时,我的意思是 tasks.relationship 看起来像一个数字,而 objects.number 以 CN 开头。
  • 除了我在该页面上的其他答案:您需要在任务的“关系”列上建立索引。您的语句将在 varchar 基础上比较这些列。那很慢。您需要整数才能更快地进行比较。索引将为您的“关系”列中的每个字符串创建哈希,并将您的搜索转换为该列上的整数搜索:) - 简单地说。注意 .. 插入和更新会更慢,因为也必须创建新索引.. 如果您处理 60.000 次插入,请记住这一点

标签: mysql


【解决方案1】:

您可以将 WHERE 条件放入 LEFT JOIN。 你真的需要左连接吗?你不能在这里使用 INNER JOIN 吗?

INNER JOIN objects ON objects.number = tasks.relationship AND tasks.status <> 'Potential'

60.000 或 15.000 个实体对于 MySQL/MariaDB 之类的数据库来说算不了什么 :)。数据库使用 Indizes 来显着改进查找,但您必须识别并创建索引。

如果您有性能问题:

  1. 尝试减少连接的行数(不要只左连接.. 有时从任务开始并连接对象可能会更好。尽可能使用内连接)

  2. 在加入之前先使用任务条件并减少行数

  3. 从您的语句中创建一个存储过程(服务器可以更快地执行它)

  4. 在搜索的重要字段上使用索引

【讨论】:

  • 考虑从左到内是有道理的。将 WHERE 条件作为 WHERE 条件与将其包含在联接中之间的确切区别是什么?
  • 在我的理解中,它将过滤任务before在Select中应用函数,而WHERE子句将过滤它们after执行这些函数每组
  • 第4点解决了问题。但所有其他的也非常有帮助。谢谢
猜你喜欢
  • 2017-09-18
  • 1970-01-01
  • 2011-10-04
  • 2019-08-13
  • 2017-12-02
  • 2011-10-17
  • 2015-11-27
  • 2017-12-24
  • 1970-01-01
相关资源
最近更新 更多