2013-03-02 110 views
0

我们有以下MySQL表有大约150万行:添加索引,优化MySQL查询

CREATE TABLE `data` (
    `datetime` datetime NOT NULL, 
    `value1` decimal(12,6) NOT NULL, 
    `value2` decimal(12,6) NOT NULL, 
    `value3` decimal(12,6) NOT NULL, 
    `value4` decimal(12,6) NOT NULL, 
    `value5` decimal(12,6) NOT NULL, 
    `symbol_id` int(11) NOT NULL, 
    PRIMARY KEY (`symbol_id`,`datetime`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 

的1.5亿行平分9500个符号之间,通过symbol_id指定。

我想这个表上运行以下查询:

SELECT datetime FROM data WHERE symbol_id = 1234 AND datetime <= "2013-03-01 15:00:00" ORDER BY datetime DESC LIMIT 1 

运行的查询返回的讲解:

  id: 1 
    select_type: SIMPLE 
     table: data 
     type: range 
possible_keys: PRIMARY 
      key: PRIMARY 
     key_len: 12 
      ref: NULL 
     rows: 23856 
     Extra: Using where; Using index 

查询平均需要运行约300毫秒。我可以添加哪些索引以加快速度?

谢谢!

+3

300毫秒,通过3.5亿行是非常好的。也许你需要考虑升级你的硬件来满足你的性能规格。 – 2013-03-02 22:31:06

+0

也在'value'字段使用'INDEX'? – hjpotter92 2013-03-02 22:32:01

+0

它实际上是150百万行,但事情是查询对某些符号运行速度非常快,但不是全部。 – user1094786 2013-03-02 22:39:49

回答

2

正如Gordon暗示的那样,没有索引可以提高查询的性能。

这并不是说你没有办法让它更快 - 调整你的DBMS和操作系统I/O - 你还没有提供任何关于它当前如何配置的信息,它的运行方式以及使用模式像。如果你还没有开始这个过程,那么对你的安装运行mysqltuner.pl将是一个好的开始 - 但它并不总是完全正确的。使用不同的引擎可以提高此查询的性能 - 但这取决于系统上正在进行的其他操作。

通过在多个磁盘上分割索引和/或使用SSD存储索引,您将获得巨大收益。更多的内存总是有帮助。

get a good book关于MySQL调优,花时间读它。

0

该查询的性能可以通过索引得到改进,但首先必须确定列的基数。

SELECT COUNT(DISTINCT `datetime`) FROM `data`; 
SELECT COUNT(DISTINCT `symbol_id`) FROM `data`; 

无论返回唯一值的最高数具有更高的基数,并具有最佳的综合指数,列必须是在降序基数顺序。

您目前有一个列按以下顺序的复合主键。

PRIMARY KEY (`symbol_id`,`datetime`) 

如果symbol_id具有比datetime更高的基数,那么查询不能进一步优化。另一方面,如果日期时间具有较高的基数,那么您应该添加一个带有日期时间后跟symbol_id的索引。

INDEX idx_datetime_symbol (`datetime`,`symbol_id`)