我有一个大约需要19秒才能运行的查询,这是很长时间的。
这是我的慢速日志的结果:
# Query_time: 19.421110 Lock_time: 0.000171 Rows_sent: 6 Rows_examined: 48515488
use c3_xchngse;
SET timestamp=1398891560;
SELECT *
FROM rates
WHERE id IN (
SELECT Max(id)
FROM rates
WHERE LOWER(`currency`) = LOWER('eur')
GROUP BY bankId
);
我尝试添加索引,例如:
ALTER TABLE `c3_xchngse`.`rates` ADD INDEX `searchIndex` ( `id` , `currency` , `bankId` )
但它似乎并没有优化查询,它们一直持续很长时间。 我也尝试为上面的查询中解决的每个列添加单独的索引,但也没有帮助。
这是我的表,今天包含大约7000行:
CREATE TABLE IF NOT EXISTS `rates` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`bankId` int(11) NOT NULL,
`currency` varchar(3) NOT NULL,
`buy` double NOT NULL,
`sell` double NOT NULL,
`addDate` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`since` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
PRIMARY KEY (`id`),
UNIQUE KEY `Unique` (`bankId`,`currency`,`since`),
KEY `bankId` (`bankId`),
KEY `currency` (`currency`),
KEY `searchIndex` (`id`,`currency`,`bankId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='The rates' AUTO_INCREMENT=6967 ;
如何优化查询或优化表格并获得完全相同的结果,但更快?
答案 0 :(得分:2)
使用LOWER(货币)会使您的索引无效。
规范化表格中的数据:
UPDATE rates SET currency = LOWER(currency) WHERE 1;
确保传递给查询的任何参数在到达查询之前都被置为小写。
此外,您可以将货币字段设置为ENUM类型以帮助进行内部索引: https://dev.mysql.com/doc/refman/5.0/en/enum.html
答案 1 :(得分:1)
这是使用join
重写查询(有时可能是有益的):
select r.*
from rates r join
(select max(id)
from rates
where `currency` = 'Eur'
group by bankId
) rmax
on r.id = rmax.id;
请注意诺亚建议删除lower()
。如果您具有区分大小写的排序规则,请确保大小写正确。不要在currency
附近放置一个函数;这排除了使用索引。您想要的索引是rates(currency, bankId, id)
。
您正在尝试为id
的每个银行查找最大eur
的所有费率信息。您也可以使用not exists
:
select r.*
from rates r
where not exists (select 1
from rates r2
where r2.bankid = r.bankid and
r2.currency = 'Eur' and
r2.id > r.id
);
使用rates(bankid, currency, id)
上的索引,这可能会有更好的效果。