如何在mysql

时间:2018-07-26 19:35:57

标签: mysql sql

我的表有大约9M行,我想删除大约270K行。我有一个有效的SQL,但无法使用索引,因此在资源上失败。

对于每一对交易所/基准货币/报价货币对,我每天都有多行(created_at)。

我的专栏是:

Id  exchange    base_currency       quote_currency  created_at

我的索引是:

ix1 id

Ix2 exchange    base_currency       quote_currency  created_at

对于每个交易所/基准货币/ quote_currency对,我想保留当天的最新行(最新ID或created_at)。因此,我找到了每天/交易所/ base_currency / quote_currency的所有MAX(id),然后尝试删除所有未选中的行(不输入)。

我的查询是:

DELETE FROM `tickers` 
WHERE
      DATE(`created_at`) = '2018-06-26'
  AND id  NOT IN 
    (SELECT MAX(id) FROM (select * FROM `tickers`) as t2 
          WHERE DATE(`created_at`) = '2018-06-26'
         GROUP BY
          exchange
         , base_currency
         , quote_currency
         , DATE(created_at)
        )

由于GROUP BY,SELECT MAX(id)使用ix2索引,但是我认为DELETE进行表扫描以使用DATE(created_at)='2018-06-26 ',这很慢。

以任何方式构造此查询,因此我也使用DELETE上的ix2索引吗?还是应该仅在created_at上创建另一个索引?

1 个答案:

答案 0 :(得分:1)

要使用索引,您需要做两件事:

  1. created_at创建索引:

    create index ix3 on `tickers` (`created_at`);
    
  2. 请通过措辞避免对where条件使用公式。例如,改用between

    DELETE FROM `tickers` 
    WHERE
          `created_at` between '2018-06-26T00:00:00' and '2018-06-26T23:59:59'
      AND id  NOT IN 
        (SELECT MAX(id) FROM (select * FROM `tickers`) as t2 
              WHERE DATE(`created_at`) = '2018-06-26'
             GROUP BY
              exchange
             , base_currency
             , quote_currency
             , DATE(created_at)
            )
    

但是,您要删除表的重要百分比(3%?)。发生这种情况时,数据库引擎可能会忽略索引,而仍然希望进行全表扫描。

您需要测试并查看数据库的用途。