【发布时间】:2019-09-27 11:15:13
【问题描述】:
为了自学,我正在为一家电力公司开发一个发票系统。我有多个时间序列表,间隔不同。一张表代表消费,另外两张代表价格。仍应包含第三个价格表。现在我正在运行计算查询,但查询速度很慢。我想提高查询速度,特别是因为这只是开始计算,查询只会变得更加复杂。另请注意,这是我创建的第一个数据库和我做过的练习。最好是简化的解释。感谢您提供的任何帮助。
我已在每个表中编入索引:DATE, PERIOD_FROM, PERIOD_UNTIL。这将过程从 60 秒加快到 5 秒。
表格的结构如下:
CREATE TABLE `apxprice` (
`APX_id` int(11) NOT NULL AUTO_INCREMENT,
`DATE` date DEFAULT NULL,
`PERIOD_FROM` time DEFAULT NULL,
`PERIOD_UNTIL` time DEFAULT NULL,
`PRICE` decimal(10,2) DEFAULT NULL,
PRIMARY KEY (`APX_id`)
) ENGINE=MyISAM AUTO_INCREMENT=28728 DEFAULT CHARSET=latin1
CREATE TABLE `imbalanceprice` (
`imbalanceprice_id` int(11) NOT NULL AUTO_INCREMENT,
`DATE` date DEFAULT NULL,
`PTU` tinyint(3) DEFAULT NULL,
`PERIOD_FROM` time DEFAULT NULL,
`PERIOD_UNTIL` time DEFAULT NULL,
`UPWARD_INCIDENT_RESERVE` tinyint(1) DEFAULT NULL,
`DOWNWARD_INCIDENT_RESERVE` tinyint(1) DEFAULT NULL,
`UPWARD_DISPATCH` decimal(10,2) DEFAULT NULL,
`DOWNWARD_DISPATCH` decimal(10,2) DEFAULT NULL,
`INCENTIVE_COMPONENT` decimal(10,2) DEFAULT NULL,
`TAKE_FROM_SYSTEM` decimal(10,2) DEFAULT NULL,
`FEED_INTO_SYSTEM` decimal(10,2) DEFAULT NULL,
`REGULATION_STATE` tinyint(1) DEFAULT NULL,
`HOUR` int(2) DEFAULT NULL,
PRIMARY KEY (`imbalanceprice_id`),
KEY `DATE` (`DATE`,`PERIOD_FROM`,`PERIOD_UNTIL`)
) ENGINE=MyISAM AUTO_INCREMENT=117427 DEFAULT CHARSET=latin
CREATE TABLE `powerload` (
`powerload_id` int(11) NOT NULL AUTO_INCREMENT,
`EAN` varchar(18) DEFAULT NULL,
`DATE` date DEFAULT NULL,
`PERIOD_FROM` time DEFAULT NULL,
`PERIOD_UNTIL` time DEFAULT NULL,
`POWERLOAD` int(11) DEFAULT NULL,
PRIMARY KEY (`powerload_id`)
) ENGINE=MyISAM AUTO_INCREMENT=61039 DEFAULT CHARSET=latin
现在运行此查询时:
SELECT i.DATE, i.PERIOD_FROM, i.TAKE_FROM_SYSTEM, i.FEED_INTO_SYSTEM,
a.PRICE, p.POWERLOAD, sum(a.PRICE * p.POWERLOAD)
FROM imbalanceprice i, apxprice a, powerload p
WHERE i.DATE = a.DATE
and i.DATE = p.DATE
AND i.PERIOD_FROM >= a.PERIOD_FROM
and i.PERIOD_FROM = p.PERIOD_FROM
AND i.PERIOD_FROM < a.PERIOD_UNTIL
AND i.DATE >= '2018-01-01'
AND i.DATE <= '2018-01-31'
group by i.DATE
我已经用 explain 运行查询并得到以下结果: Select_type, all simple partitions all null possible keys a,p = null i = DATE Key a,p = null i = DATE key_len a,p = null i = 8 ref a,p = null i = timeseries.a.DATE,timeseries.p.PERIOD_FROM 行 a = 28727 p = 61038 i = 1 过滤 a = 100 p = 10 i = 100 额外:使用 where 使用临时使用 filesort b extra: using where using join buffer (block nested loop) c extra: null
我最好运行一个更复杂的查询,针对整年并按月分组,例如包含所有价格表。但是,这太慢了。我已经在每个表中编制了索引:DATE、PERIOD_FROM、PERIOD_UNTIL。计算结果可能不会改变,在这种情况下,两米的季度小时消耗乘以小时价格。
【问题讨论】:
-
您应该考虑学习和使用现代连接语法。
-
A) 使用
JOIN。 B) 使用EXPLAIN。 -
从所涉及的条件来看,似乎
a和p在与i的关系之外是无关的。请记住,如果某个特定的i有两个a和三个p,那么您将获得该i的六个结果;i及其相关的a和p记录的每个组合。另外值得注意的是,(DATE, PERIOD_FROM, PERIOD_UNTIL) 上的索引与每个字段上的单独索引不同;并且 MySQL 只会在单个查询中使用每个表中的一个 (这就是为什么通常最好只为您的问题中的表包含实际的完整 CREATE。). -
请发布 EXPLAIN SELECT SQL_NO_CACHE ........的文本结果以供分析以及查询中涉及的 SHOW CREATE TABLE table_name(s) 和 SHOW INDEX FROM table_name(s)。
-
请学习本站的格式化工具;
EXPLAIN不可读。
标签: mysql performance indexing