如何优化 MySQL 数据库/查询

Posted

技术标签:

【中文标题】如何优化 MySQL 数据库/查询【英文标题】:How to optimize MySQL database/query 【发布时间】:2012-11-05 10:54:41 【问题描述】:

您好,我希望我能在如何优化我的数据库方面获得一些帮助,这样我就不需要一年的时间了。我知道要加快速度,我需要添加索引,但我不确定应该添加索引。

这是我数据库中的三个表:

CREATE TABLE IF NOT EXISTS `journeyPattern2` (
  `journeyPatternId` int(11) NOT NULL AUTO_INCREMENT,
  `serviceId` int(11) NOT NULL,
  `direction` enum('inbound','outbound') NOT NULL,
  PRIMARY KEY (`journeyPatternId`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

CREATE TABLE IF NOT EXISTS `journeyPatternTimingLink2` (
  `journeyPatternTimingLinkId` int(11) NOT NULL AUTO_INCREMENT,
  `journeyPatternId` int(11) NOT NULL,
  `from` varchar(15) NOT NULL,
  `to` varchar(15) NOT NULL,
  `direction` enum('inbound','outbound') NOT NULL,
  `runTime` varchar(15) NOT NULL,
  PRIMARY KEY (`journeyPatternTimingLinkId`),
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;

CREATE TABLE IF NOT EXISTS `line` (
  `lineId` int(11) NOT NULL AUTO_INCREMENT,
  `serviceId` int(11) NOT NULL,
  `lineName` tinytext NOT NULL,
  PRIMARY KEY (`lineId`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;

CREATE TABLE IF NOT EXISTS `service` (
  `serviceId` int(11) NOT NULL AUTO_INCREMENT,
  `serviceCode` varchar(50) NOT NULL,
  `registeredOperatorRef` varchar(50) NOT NULL,
  `origin` tinytext NOT NULL,
  `destination` tinytext NOT NULL,
  PRIMARY KEY (`serviceId`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;

表 JourneyPattern2 包含约 33000 行,journeyPatternTimingLink2 包含约 1300 万行,线路和服务约 70000。

我要优化的查询如下

SELECT DISTINCT lineName,line.serviceId  FROM `journeyPatternTimingLink2` 
INNER JOIN journeyPattern2
ON journeyPattern2.journeyPatternId=journeyPatternTimingLink2.journeyPatternId
INNER JOIN line
ON journeyPattern2.serviceId = line.serviceId
WHERE `from` = '13006785E'

我以前从未真正使用过这种大小的表格,所以我不确定我是否一开始就正确加入。我还上传了一个 screenshot 我在 phpmyadmin 的查询上运行 EXPLAIN,但我不确定如何解释结果,因此不胜感激。

感谢您的帮助。

【问题讨论】:

首先,您的查询真的很慢还是要提前优化? 是的,它非常慢,运行我上面发布的内容需要 50 秒。 你的解释说在journeyPattern2中有330141行,上面你说的是33000行,这是正确的吗? 是的,我只是在估计行数。我遵循了以下建议,相同的查询从 50 秒缩短到 0.04 秒。 【参考方案1】:

您必须在下面提到的列上添加一些外键索引

    jouurneyPatternId 列上的引用从journeyPattern2 添加到journeyPatternTimingLink2serviceId 列上的引用从service 添加到journeyPattern2serviceId 列上的引用从service 添加到line

journeyPatternTimingLink2 表中的from 列上添加索引。

【讨论】:

无法在使用 myisam 引擎的表上添加外键。 在该列上添加索引也可以提高性能【参考方案2】:

您应该为这些字段添加一些索引 -

journeyPatternTimingLink2.journeyPatternId journeyPattern2.serviceId line.serviceId journeyPatternTimingLink2.from

这些是在 JOIN-ON 子句和 WHERE 条件中使用的索引。

【讨论】:

【参考方案3】:

最重要的索引应该在 journeyPatternTimingLink2.from 上,因为它在您的 where 子句中,并且比所有其他表的总和多两个数量级。

您也可以考虑对所有表使用 InnoDB。来自Optimization Overview:

注意

mysql 5.5 及更高版本中,InnoDB 是新的默认存储引擎 表。在实践中,高级 InnoDB 性能特征意味着 InnoDB 表通常优于更简单的 MyISAM 表, 特别是对于繁忙的数据库。

【讨论】:

以上是关于如何优化 MySQL 数据库/查询的主要内容,如果未能解决你的问题,请参考以下文章

如何优化Mysql千万级快速分页

如何优化 MySQL 数据库/查询

MySQL查询优化:如何优化投票计算?

如何优化这个 MySQL 查询

谈谈如何优化MYSQL数据库查询

170727MySQL查询性能优化