我在这个特定的查询中有一个问题,我尝试在receiving_table中使用索引,但它仍然使用filesort,Mysql,数据库一般,不是我的强项,我还在学习基础知识,我只有8000条记录和7秒的查询很慢,我附上了我的查询和数据库,对不起英语也不是我的强项,提前谢谢
1 PRIMARY re index PRIMARY,imei_index,imeibatchclientyear,batches batches 20 8326 Using index; Using temporary; Using filesort
1 PRIMARY b ref PRIMARY,batch PRIMARY 26 tracking_system_1_schema.re.clientcode,tracking_system_1_schema.re.batchnum 1 Using where
1 PRIMARY hh eq_ref PRIMARY PRIMARY 24 tracking_system_1_schema.re.imei 1 Using where; Using index
1 PRIMARY rm eq_ref PRIMARY PRIMARY 24 tracking_system_1_schema.re.imei 1 Using where
1 PRIMARY si ref PRIMARY,imei,date date 22 func,tracking_system_1_schema.re.imei 1 Using where; Using index
1 PRIMARY h ref imei_index imei_index 30 tracking_system_1_schema.b.clientcode,tracking_system_1_schema.re.batchnum,tracking_system_1_schema.re.year 136 Using where
2 DEPENDENT SUBQUERY ssi ref PRIMARY,imei imei 17 tracking_system_1_schema.re.imei 2 Using index
EXPLAIN
SELECT
b.clientcode AS 'CUSTOMER',
b.batchnum AS 'BATCH NUMBER',
b.year,
b.datereceived AS 'DATE RECEIVED',
b.quantity AS 'BATCH QTY' ,
COUNT(DISTINCT re.imei ) + COUNT(DISTINCT IFNULL(h.imei, NULL) ) AS 'RECEIVE ITEMS',
COUNT(DISTINCT IFNULL(h.imei , NULL)) AS 'SHIPPED ITEMS',
COUNT(DISTINCT re.imei ) - COUNT(DISTINCT IF(si.processcode = 51, si.imei , NULL)) - COUNT(DISTINCT IF((hh.imei = si.imei OR rm.imei= si.imei) AND si.processcode != 51 , si.imei , NULL)) AS 'WIP',
COUNT(DISTINCT IF(si.processcode = 51, si.imei , NULL)) - COUNT(DISTINCT IF((hh.imei = si.imei OR rm.imei= si.imei) AND si.processcode = 51 , si.imei , NULL)) AS 'FGS',
COUNT(DISTINCT hh.imei) + COUNT(DISTINCT rm.imei) AS 'HOLD ITEMS'
FROM
tracking_system_1_schema.scanin_process_table si
INNER JOIN
tracking_system_1_schema.receiving_table re
ON
re.imei = si.imei
LEFT OUTER JOIN
tracking_system_1_schema.hold_table hh
ON
hh.imei = re.imei
LEFT OUTER JOIN
tracking_system_1_schema.rma_status_Table rm
ON
re.imei = rm.imei
AND
rm.status = 2
INNER JOIN
tracking_system_1_schema.batch_table b
ON
b.batchnum = re.batchnum
AND
b.clientcode = re.clientcode
AND
b.year = re.year
LEFT OUTER JOIN
item_history_1_schema.item_history_table h
ON
b.batchnum = h.batchnum
AND
b.clientcode = h.clientcode
AND
b.year = h.year
WHERE
si.dateandtime =
(
SELECT
MAX(ssi.dateandtime)
FROM
tracking_system_1_schema.scanin_process_table ssi
WHERE
ssi.imei = re.imei
)
AND
(si.dateandtime <= NOW()
OR
h.departuredate <= NOW())
GROUP BY
re.clientcode,
re.batchnum ,
re.year
;
delimiter $$
CREATE TABLE `receiving_table` (
`imei` varchar(15) NOT NULL,
`modelname` varchar(20) NOT NULL,
`batchnum` int(10) NOT NULL,
`clientcode` varchar(10) NOT NULL,
`dateandtime` datetime NOT NULL,
`status` int(11) NOT NULL DEFAULT '0',
`workerid` varchar(6) NOT NULL,
`reusecount` bigint(20) NOT NULL,
`gradebatch` varchar(30) NOT NULL,
`serialnum` varchar(15) NOT NULL,
`modifydate` datetime DEFAULT NULL,
`simcarrier` varchar(20) DEFAULT NULL,
`ismanual` int(1) DEFAULT '0',
`modelnumber` varchar(15) DEFAULT NULL,
`fccid` varchar(15) DEFAULT NULL,
`rmastatus` int(11) DEFAULT '0',
`simtraystatus` varchar(15) DEFAULT 'null',
`batchtype` int(2) DEFAULT '0',
`withlcmmarking` bit(1) NOT NULL DEFAULT b'0',
`year` int(10) NOT NULL DEFAULT '2015',
PRIMARY KEY (`imei`),
UNIQUE KEY `imei_index` (`imei`) USING BTREE,
KEY `imeibatchclientyear` (`imei`,`clientcode`,`batchnum`,`year`),
KEY `batches` (`batchnum`,`clientcode`,`year`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1$$
答案 0 :(得分:0)
首先,&#34; filesort&#34;只是一个问题。所以我不会专注于它。 GROUP BY基本上需要filesort。它并不一定意味着它触及的磁盘。
AND (si.dateandtime <= NOW() OR h.departuredate <= NOW())
将来会有参赛作品吗?如果没有,你不能摆脱这个吗?
如果确实需要,请尝试将语句转换为UNION DISTINCT。这将为优化器提供使用包含其中一列的索引的机会。
COUNT(DISTINCT)需要在UNION之外。也就是说,UNION需要在子查询中。
这是一个&#34;相关的子查询&#34;:( SELECT MAX(...) ... )
它有一个覆盖索引(好),但我们不知道它被调用的频率 - 可能超过8K次。这个可能是你7秒钟的大部分时间。尝试将其转换为JOIN ( SELECT imei, MAX(dateandtime) FROM scanin_process_table ) foo ON ...
,加上合适的行李。
请注意,使JOIN成为要处理的第一个表。所以,你需要INDEX(imei, dateandtime)
。 (我在这里的细节很模糊。)
JOIN和GROUP BY的一个普遍问题是JOIN 扩展&#34;行的数量&#34;在考虑中;那么GROUP BY 合同。请注意,您必须在COUNT中执行DISTINCT以避免不必要的重复。要查看这有多糟糕,请SELECT COUNT(*) FROM ( <your SELECT, but without the GROUP BY> ) x
;我猜它可能超过一百万。这也可能是7秒的原因。
因此,一般的解决方案是明智地将查询拆分为带有子查询的查询。唉,我看不出容易分手了。以下是部分解决方案:将b
拆分为外部查询。请注意b
的字段在任何地方都没有真正使用过。 (h
可以从re
而不是b
获得。)通过拉出b.clientcode等,tmp表不必将它们拉到周围。 (因此,百万行tmp表会更小,因此速度更快。但速度不是很快。)
您可以通过简单地删除对b的所有引用来试验拆分b。然后看看它的运行速度。然后(如果它明显更快),那么使用它:
SELECT b.clientcode ...
FROM ( <all the rest> ) x
JOIN tracking_system_1_schema.batch_table b ON b.year = x.year AND ...;
确保b具有INDEX(batchnum, clientcode, year)
- 任何顺序。