Mysql 使用<;=反对使用<;在DATETIME列上

Mysql 使用<;=反对使用<;在DATETIME列上,mysql,ruby-on-rails,activerecord,Mysql,Ruby On Rails,Activerecord,鉴于下表: desc exchange_rates; +------------------+----------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | time | datetime | NO | MUL | NULL |

鉴于下表:

desc exchange_rates;
+------------------+----------------+------+-----+---------+----------------+
| id               | int(11)        | NO   | PRI | NULL    | auto_increment | 
| time             | datetime       | NO   | MUL | NULL    |                | 
| base_currency    | varchar(3)     | NO   | MUL | NULL    |                | 
| counter_currency | varchar(3)     | NO   | MUL | NULL    |                | 
| rate             | decimal(32,16) | NO   |     | NULL    |                | 
+------------------+----------------+------+-----+---------+----------------+

我在
时间
基本货币
反货币
上添加了索引,并在(时间、基本货币、反货币)上添加了一个综合索引,但在第一种情况下,当我使用
执行
选择
时,我看到了巨大的性能差异,
MySQL
尝试合并所有索引的结果。它从两个索引中获取所有记录,并根据行指针的值(在
MyISAM
中的表偏移量,
InnoDB
中的
PRIMARY KEY
)连接它们

在第二种情况下,它只使用一个索引,考虑到
限制1
,这是最佳决策

您需要在
(基本货币、计数器货币、时间)
(按此顺序)上创建一个复合索引,以便此查询尽可能快地工作

引擎将使用索引在前导列
(基本货币、计数器货币)
上进行过滤,并在尾随列
(时间)
上进行排序

您似乎还想在查询中添加类似于
orderbytime DESC
的内容,以获取最后一次汇率


一般来说,没有按
排序的任何限额都应该会敲响警钟。

您好,谢谢,但我实际上已经在(时间、基准货币、计数器货币)上添加了一个综合指数。
@Olly
:列的顺序错误。顺序很重要。剩下的唯一一点是,为什么查询计划者在
@Michael
时输出不同的计划:我自己从来没有见过它(现在也不能复制它),但似乎大多数记录都正好在作为参数传递的时间戳内,
@OP
刚好达到了临界点,
MySQL
更喜欢一个计划而不是另一个计划。不管怎样,我们需要访问实际数据才能准确地判断。关于顺序,我认为复合索引必须反映WHERE子句中字段出现的顺序?在我的例子中,时间先到,然后是基本货币,然后是反货币,因此我使用(时间、基本货币、反货币)创建了索引。这不对吗?过程分析()说了什么?
ExchangeRate Load (95.5ms)   
SELECT * FROM `exchange_rates` WHERE (time <= '2009-12-30 14:42:02' and base_currency = 'GBP' and counter_currency = 'USD') LIMIT 1
ExchangeRate Load (0.8ms)   
SELECT * FROM `exchange_rates` WHERE (time < '2009-12-30 14:42:02' and base_currency = 'GBP' and counter_currency = 'USD') LIMIT 1
-- Output from the first, slow, select
SIMPLE      | 5,5     | exchange_rates | 1  | index_exchange_rates_on_time,index_exchange_rates_on_base_currency,index_exchange_rates_on_counter_currency,time_and_currency | index_merge | Using intersect(index_exchange_rates_on_counter_currency,index_exchange_rates_on_base_currency); Using where | 813  |     | index_exchange_rates_on_counter_currency,index_exchange_rates_on_base_currency

-- Output from the second, fast, select
SIMPLE      | 5       | exchange_rates | 1  | index_exchange_rates_on_time,index_exchange_rates_on_base_currency,index_exchange_rates_on_counter_currency,time_and_currency | ref  | Using where | 4988 | const | index_exchange_rates_on_counter_currency