MySQL在大数据集上的低效查询

MySQL在大数据集上的低效查询,mysql,bigdata,Mysql,Bigdata,我们有一个类似这样的MySQL表(删除了不重要的列): 表中大约有9亿行,其中一个帐户id占这些行的65%以上。我被要求为创建的和发布的日期范围写查询,这取决于帐户id,它似乎对自动递增键有1:1的功能依赖性 典型的查询如下所示: SELECT * FROM my_data WHERE account_id = 1 AND created_ts > TIMESTAMP('2012-01-01') AND created_ts <= TIMESTAMP(

我们有一个类似这样的MySQL表(删除了不重要的列):

表中大约有9亿行,其中一个帐户id占这些行的65%以上。我被要求为创建的和发布的日期范围写查询,这取决于帐户id,它似乎对自动递增键有1:1的功能依赖性

典型的查询如下所示:

SELECT * 
FROM my_data 
WHERE account_id = 1 AND 
      created_ts > TIMESTAMP('2012-01-01') AND 
      created_ts <= TIMESTAMP('2012-01-21') 
ORDER BY created_ts DESC LIMIT 100;
问题是查询花费的时间太长,最终被终止。我已经让它运行了几次,它导致数据库主机停机,因为操作系统(Linux)的交换空间不足

我反复研究了这个问题,并试图将查询分解为不相关的子查询,强制索引,使用显式SELECT子句,并限制日期范围的窗口,但结果是一样的:性能差(太慢),主机负担太重(总是死的)

我的问题是:

  • 是否可以制定一个查询,将数据分割成日期范围,并为实时调用执行可接受的操作?(<1s)

  • 为了获得要求的性能,是否有我缺少的或可能有帮助的优化

  • 欢迎任何其他建议、提示或想法


    感谢

    似乎mysql对此查询使用了错误的索引,请尝试强制执行另一个:

    SELECT * 
    FROM my_data FORCE INDEX (`account_created_idx`)
    WHERE account_id = 1 AND 
          created_ts > TIMESTAMP('2012-01-01') AND 
          created_ts <= TIMESTAMP('2012-01-21') 
    ORDER BY created_ts DESC LIMIT 100;
    
    选择*
    从my_数据强制索引(`account_created_idx`)
    其中account_id=1和
    创建时间戳(“2012-01-01”)和
    创建\u ts试试MariaDB(或MySQL 5.6),因为他们的优化器可以更快地完成。
    我已经用了几个月了,对于像你这样的一些查询,它比以前快了1000%

    您需要索引条件下推:
    不要在比较中使用函数。计算时间戳并使用计算出的值,否则您无法使用索引来比较创建的数据,而该字段将从结果集中过滤数百万行。不确定MySQL为什么使用(显然)不是最佳索引。除了强制索引外,您是否可以尝试此变体的
    EXPLAIN
    计划:

    SELECT * 
    FROM my_data 
    WHERE account_id = 1 AND 
          created_ts > TIMESTAMP('2012-01-01') AND 
          created_ts <= TIMESTAMP('2012-01-21') 
    ORDER BY account_id
           , created_ts DESC 
    LIMIT 100;
    
    选择*
    从我的数据
    其中account_id=1和
    创建时间戳(“2012-01-01”)和
    
    这个问题多年来一直存在。尽管如此,还是有一个很好的答案

    你奋斗的关键在于你的言辞。当您执行
    SELECT*。。。。按X描述限制N下单
    。这是因为整个结果集必须被挑选和洗牌。当您要求一个复杂表中的所有列时,这是大量的数据

    对于
    WHERE
    子句,您有一个很好的索引。如果
    orderby
    子句中没有说
    DESC
    ,那么它对该子句也有好处

    您需要的是延迟加入。首先只检索所需行的ID

            SELECT auto_id
              FROM my_data
             WHERE account_id = 1 AND 
                  created_ts > TIMESTAMP('2012-01-01') AND 
                  created_ts <= TIMESTAMP('2012-01-21') 
         ORDER BY created_ts DESC
            LIMIT 100
    
    试试这个。这可能会为你节省很多时间

    如果你先验地知道自动id和创建id都是单调递增的,那么你可以做得更好。您的子查询可以包含

          ORDER BY auto_id DESC
             LIMIT 100
    
    这将减少需要进一步洗牌的数据


    专业提示:避免在生产系统中选择*
    ;而是枚举实际需要的列。原因有很多。

    删除Order by子句后检查性能。MySQL 5.6不是一个稳定的版本。还没有,我知道。这只是为了增加更多的信息。我正在使用MariaDB,因为该产品正在生产阶段。非常感谢。不知道有关力索引的信息+如果可以的话。
            SELECT auto_id
              FROM my_data
             WHERE account_id = 1 AND 
                  created_ts > TIMESTAMP('2012-01-01') AND 
                  created_ts <= TIMESTAMP('2012-01-21') 
         ORDER BY created_ts DESC
            LIMIT 100
    
    SELECT a.*
      FROM my_data a
      JOIN (
                 SELECT auto_id
                   FROM my_data
                  WHERE account_id = 1 AND 
                        created_ts > TIMESTAMP('2012-01-01') AND 
                        created_ts <= TIMESTAMP('2012-01-21') 
               ORDER BY created_ts DESC
                  LIMIT 100
           ) b ON a.auto_id = b.auto_id
     ORDER BY a.created_ts DESC
    
          ORDER BY auto_id DESC
             LIMIT 100