MySQL的查询速度非常慢
我试图学习MySQL的优化、表引擎以及何时使用它们等等 我有一个查询正在运行,超过了10分钟的超时限制,需要在几秒钟内完成,因为它的功能是用户生成的报告 查询:MySQL的查询速度非常慢,mysql,performance,Mysql,Performance,我试图学习MySQL的优化、表引擎以及何时使用它们等等 我有一个查询正在运行,超过了10分钟的超时限制,需要在几秒钟内完成,因为它的功能是用户生成的报告 查询: SELECT em.employeeId, tsk.taskId FROM employee em INNER JOIN task tsk ON tsk.employeeId = em.employeeId WHERE em.employeeId
SELECT em.employeeId, tsk.taskId
FROM employee em INNER JOIN
task tsk
ON tsk.employeeId = em.employeeId
WHERE em.employeeId <> 'Not Done'
AND tsk.employeeId (
SELECT employeeId FROM task
WHERE templateId
IN ( '5', '6', '7', '8' )
AND tsk.status = 'Done'
)
AND tsk.employeeId IN
(
SELECT employeeId FROM task
WHERE templateId IN
( '55', '56', '57', '58' )
AND status = 'Not Done'
)
DB服务器使用MyISAM作为默认模式,因此包括此模式在内的大多数模式都是MyISAM
我还意识到文本搜索status=Done或类似于“Done”的状态为查询添加了很多内容
编辑1:
# Table, Create Table
employee, CREATE TABLE `employee` (
`employeeId` int(10) unsigned NOT NULL AUTO_INCREMENT,
`lastName` varchar(255) NOT NULL,
`firstName` varchar(255) NOT NULL,
`applicantId` varchar(255) NOT NULL,
`fEmployeeId` varchar(255) DEFAULT NULL,
`opId` varchar(255) DEFAULT NULL,
`rehire` tinyint(3) unsigned NOT NULL DEFAULT '0',
`sDate` date DEFAULT NULL,
`oDate` date DEFAULT NULL,
`cDate` date DEFAULT NULL,
`additionalDate` date DEFAULT NULL,
`additionalType` varchar(255) DEFAULT NULL,
`processingDate` date DEFAULT NULL,
`created` datetime NOT NULL,
`recruiterId` int(10) unsigned NOT NULL,
`processorId` int(10) unsigned DEFAULT NULL,
`position` tinyint(3) unsigned NOT NULL DEFAULT '1',
`status` varchar(255) NOT NULL,
`campus` varchar(255) DEFAULT NULL,
`phone` varchar(255) DEFAULT NULL,
`email` varchar(255) DEFAULT NULL,
`requisition` varchar(255) DEFAULT NULL,
`Position` varchar(255) DEFAULT NULL,
`department` varchar(255) DEFAULT NULL,
`jobClass` varchar(255) DEFAULT NULL,
`hiringManager` varchar(255) DEFAULT NULL,
`badge` varchar(255) DEFAULT NULL,
`currentAddress` varchar(255) DEFAULT NULL,
`holding` tinyint(3) unsigned DEFAULT '0',
PRIMARY KEY (`employeeId`)
) ENGINE=MyISAM AUTO_INCREMENT=3959 DEFAULT CHARSET=latin1
编辑2:
# Table, Create Table
task, CREATE TABLE `task` (
`taskId` int(10) unsigned NOT NULL AUTO_INCREMENT,
`templateId` int(10) unsigned NOT NULL,
`employeeId` int(10) unsigned NOT NULL,
`name` varchar(255) NOT NULL,
`description` text,
`naAvailable` tinyint(3) unsigned DEFAULT '0',
`fileRequired` tinyint(3) unsigned DEFAULT '0',
`fileHrCatalog` int(10) unsigned DEFAULT NULL,
`quickFileName` varchar(255) DEFAULT NULL,
`fileUploaded` tinyint(3) unsigned DEFAULT '0',
`fileExt` varchar(255) DEFAULT NULL,
`level` tinyint(3) unsigned NOT NULL,
`status` varchar(255) NOT NULL,
`due` date DEFAULT NULL,
`daysDue` int(10) unsigned DEFAULT NULL,
`routeIncentives` tinyint(3) unsigned DEFAULT '0',
`requiresAudit` tinyint(3) unsigned DEFAULT '0',
`auditStatus` varchar(255) DEFAULT NULL,
`auditUser` int(10) unsigned DEFAULT NULL,
`auditDate` datetime DEFAULT NULL,
`stampOption` tinyint(3) unsigned DEFAULT '0',
`done` tinyint(3) unsigned DEFAULT '0',
`doneBy` int(10) unsigned DEFAULT NULL,
`doneWhen` datetime DEFAULT NULL,
`sortOrder` tinyint(3) unsigned NOT NULL DEFAULT '255',
PRIMARY KEY (`taskId`),
KEY `status` (`status`,`templateId`)
) ENGINE=MyISAM AUTO_INCREMENT=176802 DEFAULT CHARSET=latin1
您的第一个更改应该是在任务上创建一个包含status和templateId列的索引: 这将阻止每次在查询中访问61326行的完整表扫描 此外,您可能在此处输入了一个错误:
SELECT employeeId FROM task
WHERE templateId
IN ( '5', '6', '7', '8' )
AND tsk.status = 'Done'
该tsk.status应该与第二个子查询一样是status。您的第一个更改应该是创建一个包含status和templateId列的任务索引: 这将阻止每次在查询中访问61326行的完整表扫描 此外,您可能在此处输入了一个错误:
SELECT employeeId FROM task
WHERE templateId
IN ( '5', '6', '7', '8' )
AND tsk.status = 'Done'
该tsk.status应该与第二个子查询一样是status。我将按如下方式编写查询,但为了帮助优化,请在表上设置一个覆盖索引 Employee表-状态索引,employeeID 任务表-关于employeeid、templateid和status的索引 在第一次加入时,您将预先获得第一个任务作为完成状态的资格 第二个连接是寻找您感兴趣但尚未完成的其他任务 执行子查询,尤其是相关子查询,可能会对性能造成更大的影响。通过连接,它要么在那里,要么不在那里
SELECT
em.employeeId,
tsk.taskId
FROM
employee em
INNER JOIN task tsk1
ON em.employeeId = tsk1.employeeId
AND tsk1.templateID in ( '5', '6', '7', '8' )
AND tsk1.status = 'Done'
INNER JOIN task tsk2
ON em.employeeId = tsk2.employeeId
AND tsk2.templateID in ( '55', '56', '57', '58' )
AND tsk2.status = 'Not Done'
WHERE
em.status <> 'Not Done'
我将按如下方式编写查询,但为了帮助优化,请在表上设置一个覆盖索引 Employee表-状态索引,employeeID 任务表-关于employeeid、templateid和status的索引 在第一次加入时,您将预先获得第一个任务作为完成状态的资格 第二个连接是寻找您感兴趣但尚未完成的其他任务 执行子查询,尤其是相关子查询,可能会对性能造成更大的影响。通过连接,它要么在那里,要么不在那里
SELECT
em.employeeId,
tsk.taskId
FROM
employee em
INNER JOIN task tsk1
ON em.employeeId = tsk1.employeeId
AND tsk1.templateID in ( '5', '6', '7', '8' )
AND tsk1.status = 'Done'
INNER JOIN task tsk2
ON em.employeeId = tsk2.employeeId
AND tsk2.templateID in ( '55', '56', '57', '58' )
AND tsk2.status = 'Not Done'
WHERE
em.status <> 'Not Done'
表上有什么索引?请提供SHOW CREATE TABLE employee和SHOW CREATE TABLE task的输出。表上有哪些索引?请提供SHOW CREATE TABLE employee和SHOW CREATE TABLE task的输出,感谢您的输入…第一个状态实际上是一个输入错误,谢谢。我添加了索引,并将报告查询时间的差异。此外,外部选择em.employeeId“未完成”应该是em.status建议更改后,查询时间下降到34.5秒。感谢您的输入…第一个状态实际上是一个输入错误,谢谢。我添加了索引,并将报告查询时间的差异。此外,外部选择em.employeeId“Not Done”应该是em.status建议更改后,查询时间减少到34.5秒。这是一个相当大的改进,0.015秒。感谢您提供了一种不同的方式来查看子查询……我没有想过以这种方式加入它们。@DanielV.,只是稍微快一点而已??。。。很高兴它成功了:这是一个相当大的进步,0.015秒。感谢您提供了一种不同的方式来查看子查询……我没有想过以这种方式加入它们。@DanielV.,只是稍微快一点而已??。。。很高兴它成功了: