简体   繁体   English

优化MySQL表索引/查询

[英]Optimizing MySQL table index/query

I have a query which takes about 19 seconds to run, which is waaaay to long time. 我有一个查询,大约需要19秒钟才能运行,这很长一段时间。

This is the result from my slow log: 这是我的慢日志的结果:

# 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
                );

I have tried to add indexes such as: 我试图添加索引,例如:

ALTER TABLE  `c3_xchngse`.`rates` ADD INDEX  `searchIndex` (  `id` ,  `currency` ,  `bankId` )

But it doesn't seem to optimize the queries, they keep taking way to long time. 但是它似乎并没有优化查询,它们一直持续很长时间。 I have also tried added seperate index for each column addressed in the query above, but no help there either. 我也尝试为上面查询中解决的每一列添加单独的索引,但是那里也没有帮助。

This is my table, which contains today about 7000 rows: 这是我的表,今天包含大约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 ;

How can I either optimize my query or optimize the table and get the exact same results, but faster? 如何优化查询或优化表并获得完全相同的结果,但速度更快?

Using LOWER(currency) is rendering your index useless. 使用LOWER(currency)会使索引无用。

Normalize the data in the table: 标准化表中的数据:

UPDATE rates SET currency = LOWER(currency) WHERE 1;

And make sure that any arguments passed into the query are put into lowercase before it hits the query. 并确保传递给查询的所有参数在命中查询之前都被转换为小写。

Additionally, you can make the currency field an ENUM type to help with internal indexing: https://dev.mysql.com/doc/refman/5.0/en/enum.html 另外,您可以将货币字段设置为ENUM类型以帮助进行内部索引编制: https : //dev.mysql.com/doc/refman/5.0/en/enum.html

This is a rewrite of the query using a join (which can sometimes be beneficial): 这是使用所述查询的重写join (其有时可以是有益的):

select r.*
from rates r join
     (select max(id)
      from rates
      where `currency` = 'Eur'
      group by bankId
     ) rmax
     on r.id = rmax.id;

Note the removal of lower() as Noah suggested. 请注意,如Noah所建议的,删除了lower() If you have a case sensitive collation, make sure you have the case correct. 如果您有区分大小写的排序规则,请确保大小写正确。 Don't put a function around currency ; 不要围绕currency发挥作用; that precludes the use of an index. 排除了索引的使用。 The index that you want for this is rates(currency, bankId, id) . 为此所需的索引是rates(currency, bankId, id)

You are trying to find all the rate information for the biggest id for each bank for eur . 你正在努力寻找所有的最大速率信息id对每个银行eur You can also express this using not exists : 您也可以使用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
                 );

With an index on rates(bankid, currency, id) this might perform better. 使用rates(bankid, currency, id)索引rates(bankid, currency, id)可能会更好。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM