【问题标题】:telling if key exists in mysql table is taking too long判断 mysql 表中是否存在键需要太长时间
【发布时间】:2013-03-14 23:05:21
【问题描述】:

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

我从那个问题中找到的答案是令人满意的。我有一个包含 2200 万行的表,我希望将其增加到大约 1 亿行。这时候表minute_data的结构是这样的:

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

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

当表包含值“CSCO”时,这非常快(

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 添加主键(符号,日期);

3) INSERT IGNORE INTO minute_data_2 SELECT * FROM minute_data;

4) DROP TABLE 分钟数据;

5) 将 minute_data_2 重命名为 minute_data

现在,我看到上面描述的相同查询的速度快得令人眼花缭乱,耗时超过 180 秒,现在在 0.001 秒内完成。太棒了。

【问题讨论】:

    标签: mysql database optimization query-optimization


    【解决方案1】:

    您是否尝试过使用 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,这意味着排序是按时间戳然后按符号。如果您只有一个复合索引,其中时间戳是第一位的,您可能希望在符号上放置单独的索引。

    【讨论】:

    • 是的,我确实尝试了EXISTS 查询,它的性能与我上面提到的查询相同......这个查询大约需要30秒:select EXISTS(SELECT * FROM minute_data WHERE symbol = "ABCD");
    • 你说得对,我的PK是在(日期,符号)合成的。如果将其定义为(符号,日期),将symbol 放在首位,会有所不同吗?我也可以试试符号上的索引。
    • 他的意思是你应该只在符号上添加索引
    • @jeffery_the_wind - 如果您的大多数查询都有一个有限符号子句(1 个符号或 IN(list_of_symbols),则最好将符号列放在复合键的首位。添加索引仅在符号列上是一种(它运行缓慢,所以......)hacky解决方案,但也可以。
    • 感谢您的意见。我认为切换主键的顺序也是正确的想法。我已经成功地从表中删除了旧的主键设置,但是我很难设置新的主键。我使用查询:alter table minute_data add primary key (symbol, data),每次在大约 600 秒后出现错误:2031: Lost connection to MySQL server...,即使它在本地主机上。
    【解决方案2】:

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

    符号
    symbol_id(INT,主键,自动增量)
    符号文本(VARCHAR)

    分钟数据
    key_col(BIGINT、主键、自动增量)
    symbol_id(INT,索引)
    其他字段

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

    尽量避免重复输入到您的表中..

    【讨论】:

    • 这似乎没有解决我的问题,因为我需要在 minute_data 表中唯一的日期/符号组合。
    猜你喜欢
    • 2010-12-10
    • 2012-03-17
    • 1970-01-01
    • 1970-01-01
    • 2012-01-13
    • 1970-01-01
    • 1970-01-01
    • 2019-06-07
    • 1970-01-01
    相关资源
    最近更新 更多