为什么这个简单的查询需要超过 1 秒?

rat*_*ace 5 mysql performance slow-log

该表有大约 1700 万行,是 MyISAM。

select DateModified,PELTM,PSLTM 
from financial_key_ratios 
where SecurityId = 4525 
  and DateModified >= '2015-01-07';
Run Code Online (Sandbox Code Playgroud)

这个简单的查询似乎需要超过 1 秒的时间。

索引似乎没问题。这是解释的输出:

 explain 
 select DateModified,PELTM,PSLTM 
 from financial_key_ratios 
 where SecurityId = 4525 
   and DateModified >= '2015-01-07';
+----+-------------+----------------------+-------+------------------------------------------------+------------+---------+------+------+-------------+
| id | select_type | table                | type  | possible_keys                                  | key        | key_len | ref  | rows | Extra       |
+----+-------------+----------------------+-------+------------------------------------------------+------------+---------+------+------+-------------+
|  1 | SIMPLE      | financial_key_ratios | range | SecurityId,secid,DateModified_index,secid_date | secid_date | 7       | NULL |  156 | Using where |
+----+-------------+----------------------+-------+------------------------------------------------+------------+---------+------+------+-------------+
Run Code Online (Sandbox Code Playgroud)

我们可能做错了什么?

CREATE TABLE `financial_key_ratios` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `SecurityId` int(11) NOT NULL,
  `PELTM` decimal(12,4) NOT NULL,
  `PSLTM` decimal(12,4) NOT NULL,
  `POCFLTM` decimal(12,4) NOT NULL,
  `PEG` decimal(12,4) NOT NULL,
  `PBV` decimal(12,4) NOT NULL,
  `EVEBTIDA` decimal(12,4) NOT NULL,
  `Evbyrevenue` decimal(12,4) NOT NULL,
  `Fcf_yeild` decimal(12,4) NOT NULL,
  `Earnings_yeild` decimal(12,4) NOT NULL,
  `Pe_annualized` decimal(12,4) NOT NULL,
  `Pbys_annualized` decimal(12,4) NOT NULL,
  `Pbybv_annualized` decimal(12,4) NOT NULL,
  `Evbyebitda_annualized` decimal(12,4) NOT NULL,
  `Evbyrevenue_annualized` decimal(12,4) NOT NULL,
  `Pe_ltm_adj` decimal(12,4) NOT NULL,
  `Enterprise_value` decimal(12,4) NOT NULL,
  `Marketcap` decimal(12,4) NOT NULL,
  `DividendYield` decimal(12,4) NOT NULL,
  `DateModified` date NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `SecurityId` (`SecurityId`,`DateModified`),
  KEY `secid` (`SecurityId`),
  KEY `DateModified_index` (`DateModified`),
  KEY `secid_date` (`SecurityId`,`DateModified`)
) ENGINE=MyISAM AUTO_INCREMENT=65138826 DEFAULT CHARSET=latin1 |
Run Code Online (Sandbox Code Playgroud)

更新:

我已经有了所有的索引。它并不总是很慢。在 14K 请求中,它在慢查询日志中报告了大约 100 次。

这是慢查询日志的更新

Time=1.22s (68s)  Lock=0.00s (0s)  Rows=249.2 (13955), 
select DateModified,PELTM,PSLTM from financial_key_ratios
where SecurityId = N and DateModified >= 'S'
Run Code Online (Sandbox Code Playgroud)

Gre*_*reg 1

我不是 MySQL 专家,但在我看来,它正在按 secid_date 进行表扫描,而这根本不在查询中。扫描 17M 行并不是您想要做的事情,除非您真的必须这样做。

检查你的索引

mysql> SHOW INDEX FROM financial_key_ratios\G
Run Code Online (Sandbox Code Playgroud)

我会确保你有类似的东西

+-----------------------+------------+------------+--------------+---------------+ ... 
| Table                 | Non_unique | Key_name   | Seq_in_index | Column_name   | ... 
+-----------------------+------------+------------+--------------+---------------+ ... 
| financial_key_ratios  |          1 | ...        |            1 | SecurityId    | ... 
Run Code Online (Sandbox Code Playgroud)

如果可能的话

| financial_key_ratios  |          1 | ...        |            2 | DateModified  | ... 
Run Code Online (Sandbox Code Playgroud)

如果您没有至少在 SecurityId 上建立索引,则可以使用以下命令添加它

CREATE INDEX IdxSecurityId ON financial_key_ratios (SecurityId)
Run Code Online (Sandbox Code Playgroud)

您可以更进一步,包括 DateModified

CREATE INDEX IdxSecurityId_DateModified ON financial_key_ratios (SecurityId, DateModified)
Run Code Online (Sandbox Code Playgroud)