我在 MySql 服务器中有一个非常慢的查询。
我添加查询:
SELECT CRR_DT, TOU, SRCE, SINK, NAME, SEASON, SRCESUMCONG, SINKSUMCONG,
SRCEAVGCONG, SINKAVGCONG, SUMSINKMSRCE, AVGSINKMSRCE,
HOURCOUNT, TERM, START_DT, END_DT, CTYPE, MW AS MW_AWARD,
Mark, SCID
FROM
( SELECT a.CRR_DT, a.TOU, a.SRCE, a.SINK, a.NAME, a.SEASON, a.SRCESUMCONG,
a.SINKSUMCONG, a.SRCEAVGCONG, a.SINKAVGCONG, a.SUMSINKMSRCE,
a.AVGSINKMSRCE, a.HOURCOUNT, b.TERM, b.CTYPE, b.START_DT,
b.END_DT, b.MW, b.SCID, b.Mark
FROM
( SELECT CRR_DT, TOU, SRCE, SINK, NAME, SEASON, SRCESUMCONG, SINKSUMCONG,
SRCEAVGCONG, SINKAVGCONG, SUMSINKMSRCE, AVGSINKMSRCE,
HOURCOUNT
FROM CRR_CONGCALC
WHERE CRR_DT >= '2015-01'
) a
INNER JOIN
( SELECT MARKET, TERM, TOU, SRCE, SINK, NAME, SCID, CTYPE, START_DT,
END_DT, SUM(MW) AS MW, SUBSTR(MARKET, 1, 3) AS MARK
FROM CRR_INVENTORY
WHERE COPTION = 'OBLIGATION'
AND START_DT >= '2015-01-01'
AND SCID IN ('EAGL' , 'LDES')
GROUP BY MARKET , TOU , SRCE , SINK , NAME , SCID , CTYPE ,
START_DT , END_DT
) b ON a.NAME = b.NAME
AND a.TOU = b.TOU
) c
WHERE c.CRR_DT BETWEEN SUBSTR(c.START_DT, 1, 7) AND SUBSTR(c.END_DT, 1, 7 )
ORDER BY NAME , CRR_DT , TOU ASC
这里是使用 MysQl Workbrench 生成的 Explain plan
结果
我猜红色 block 红色很危险。有人可以帮助我理解这个计划吗?关于我在制定此执行计划后应该检查哪些内容的一些提示。
编辑添加表格布局
CREATE TABLE `CRR_CONGCALC` (
`CRR_DT` varchar(7) NOT NULL,
`TOU` varchar(50) NOT NULL,
`SRCE` varchar(50) NOT NULL,
`SINK` varchar(50) NOT NULL,
`SRCESUMCONG` decimal(12,6) DEFAULT NULL,
`SINKSUMCONG` decimal(12,6) DEFAULT NULL,
`SRCEAVGCONG` decimal(12,6) DEFAULT NULL,
`SINKAVGCONG` decimal(12,6) DEFAULT NULL,
`SUMSINKMSRCE` decimal(12,6) DEFAULT NULL,
`AVGSINKMSRCE` decimal(12,6) DEFAULT NULL,
`HOURCOUNT` int(11) NOT NULL DEFAULT '0',
`SEASON` char(1) NOT NULL DEFAULT '0',
`NAME` varchar(110) NOT NULL,
PRIMARY KEY (`CRR_DT`,`SRCE`,`SINK`,`TOU`,`HOURCOUNT`),
KEY `srce_index` (`SRCE`),
KEY `srcesink` (`SRCE`,`SINK`)
)
CREATE TABLE `CRR_INVENTORY` (
`MARKET` varchar(50) NOT NULL,
`TERM` varchar(50) NOT NULL,
`TOU` varchar(50) NOT NULL,
`INVENTORY_DT` date NOT NULL,
`START_DT` datetime NOT NULL,
`END_DT` datetime NOT NULL,
`CRR_ID` varchar(50) NOT NULL,
`NSR_INDEX` tinyint(1) NOT NULL,
`SEGMENT` tinyint(1) NOT NULL,
`CTYPE` varchar(50) NOT NULL,
`CATEGORY` varchar(50) NOT NULL,
`COPTION` varchar(50) NOT NULL,
`SRCE` varchar(50) DEFAULT NULL,
`SINK` varchar(50) DEFAULT NULL,
`MW` decimal(8,4) NOT NULL,
`SCID` varchar(50) NOT NULL,
`SEASON` char(1) DEFAULT '0',
`NAME` varchar(110) NOT NULL,
PRIMARY KEY (`MARKET`,`INVENTORY_DT`,`CRR_ID`),
KEY `srcesink` (`SRCE`,`SINK`)
)
最佳答案
唤起记忆。对于数据库,“全表扫描”意味着数据库无法用来加速查询,它会读取整个表。 行以未排序的顺序存储,因此没有更好的方法来“搜索”您要查找的员工 ID。
这很糟糕。为什么?
如果你有一个包含一堆列的表:
first_name, last_name, employee_id, ..., column50
并搜索 where employee_id = 1234
,如果您在 employee_id 列上没有索引,那么您是进行顺序扫描。如果您在 table1.employee_id = table2.eid 上执行 join table2
,情况会更糟,因为它必须将 employee_id 与连接表中的每条记录相匹配。
如果您创建索引,您可以大大减少查找匹配项(或丢弃不匹配项)的扫描时间,因为您可以搜索排序字段而不是进行顺序扫描。快得多。
当您在 employee_id 字段上创建索引时,您正在创建一种搜索员工编号的方法,该方法的速度要快得多。 当您创建索引时,您是在说“我将根据此字段加入或有一个基于此字段的 where 子句”。这会以占用少量磁盘空间为代价加快您的查询速度。
索引有各种各样的技巧,你可以创建它们,使它们是唯一的、不唯一的、复合的(包含多列)和各种各样的东西。发布您的查询,我们可以告诉您您可能会考虑建立索引以加快查询速度。
一个好的经验法则是,您应该在您的表中为您在 where 子句、连接条件或排序依据中使用的字段创建索引。选择领域取决于一些超出本次讨论范围的事情,但这应该是一个开始。
关于mysql - 是否可以提高此查询的性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31258237/