告诉mysql表中是否存在密钥需要太长时间

时间:2013-03-25 12:43:30

标签: mysql database optimization query-optimization

我从这个问题开始:is my large mysql table destined for failure?

我从这个问题中找到的答案令人满意。我有一个2200万行的表,我想增长到大约1亿行。此时,表minute_data结构如下所示: enter image description here

我遇到的问题如下。我需要执行这个查询:

select datediff(date,now()) from minute_data  where symbol = "CSCO" order by date desc limit 1;

当表包含值“CSCO”时,速度非常快(<1秒)。问题是,有时我会查询表中没有的符号。当我执行这样的查询时,例如,symbol =“ABCD”:

select datediff(date,now()) from minute_data  where symbol = "ABCD" order by date desc limit 1;

然后查询需要很长时间......就像永远(180秒)。

我可以解决这个问题的方法是确保在执行查询之前表格包含我要查找的符号。我发现这样做的最快方法是使用跟随查询,我只需要用它来检查表minute_data是否包含我要查找的符号。基本上我只需要它返回一个布尔值,所以我知道符号是否在表中:

select count(1) from minute_data where symbol = "CSCO";

此查询需要超过30秒才能返回1个值,这对我来说太长了,因为上面的查询实际返回datediff计算只需不到1秒。

symbol列是pri键的一部分,我认为它应该能够很快找出值是否存在。

我做错了什么?有没有快速的方法来做我想做的事情?我应该更改数据结构以优化性能吗?

谢谢!

更新

我想我找到了解决这个问题的好方法。从LastCoder下面的答案中,我做了以下几点:

1)创建了一个名为minute_data_2的新表,其定义与minute_data完全相同。

2)     ALTER TABLE minute_data_2 ADD PRIMARY KEY(符号,日期);

3)     INSERT IGNORE INTO minute_data_2 SELECT * FROM minute_data;

4)     DROP TABLE minute_data;

5)将minute_data_2重命名为minute_data

现在我看到同样的查询速度非常快,我上面描述的时间超过180秒,现在在0.001秒内完成。惊人的。

2 个答案:

答案 0 :(得分:2)

您是否尝试过使用EXISTS(...)

select datediff(date,now()) from minute_data  
where EXISTS(SELECT * FROM minute_data WHERE symbol = "CSCO") 
AND symbol = "CSCO" order by date desc limit 1;

即使符号是主键,看起来你也有时间戳作为PK,这让我觉得你正在使用COMPOSITE pk,这意味着顺序是按时间戳然后是符号。您可能希望在符号上放置单独的索引,如果您拥有的只是时间戳为第一个的复合索引。

答案 1 :(得分:0)

我认为最好创建一个名为symbols的表,并在minute_data表中添加对该表的引用:

<强>符号
symbol_id(INT,Primary Key,Auto Increment)
symbol_text(VARCHAR)

<强> minute_data
key_col(BIGINT,Primary Key,Auto Increment)
symbol_id(INT,Index)
other_field

使用InnoDB作为表类型来添加引用。

尽量避免重复输入表格。