【问题标题】:How do you group, bucket, and filter a result sets for a very large dataset您如何对非常大的数据集的结果集进行分组、存储和过滤
【发布时间】:2011-03-26 11:51:32
【问题描述】:

抱歉,问题的标题有点模糊,所以这是一个工作示例。

我有一个表,每个用户(用户 ID)每隔几天就会在其中获取一个值。我想为每个用户找到这些值中的最后一个,按月细分,并将它们的数量计算到一个范围内。

这是一个示例表和代表性数据:

CREATE TABLE `datasource` (
    `id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY ,
    `userId` INT UNSIGNED NOT NULL ,
    `unixts` INT UNSIGNED NOT NULL ,
    `value` INT UNSIGNED NOT NULL ,
    INDEX ( `userId` )
);

INSERT INTO `datasource` 
    (`userId`, `unixts`, `value`)
VALUES 
    (1, UNIX_TIMESTAMP('2010-07-01'), 500),
    (1, UNIX_TIMESTAMP('2010-07-15'), 610),
    (1, UNIX_TIMESTAMP('2010-08-02'), 740),

    (2, UNIX_TIMESTAMP('2010-07-03'), 506),
    (2, UNIX_TIMESTAMP('2010-07-18'), 640),
    (2, UNIX_TIMESTAMP('2010-08-09'), 340),

    (3, UNIX_TIMESTAMP('2010-07-03'), 506),
    (3, UNIX_TIMESTAMP('2010-08-18'), 640)
;

现在,这里有一个查询来获取我想要的内容:

select
    month(FROM_UNIXTIME(unixts)) as month,
    sum( if( value >= 700, 1, 0) ) as '700 and up',
    sum( if( value BETWEEN 600 AND 699, 1, 0) ) as '600-699',
    sum( if( value BETWEEN 500 AND 599, 1, 0) ) as '500-599',
    sum( if( value <= 499, 1, 0) ) as '499 and below',
    count(*) as total
from
    datasource
where
    id in (
        select 
            max(id)
        from 
            datasource 
        where 
            unixts between UNIX_TIMESTAMP('2010-07-01') and UNIX_TIMESTAMP('2010-09-01')
        group by 
            userId, month(from_unixtime(unixts))
    )
group by
    month(FROM_UNIXTIME(unixts));

+-------+------------+---------+---------+---------------+-------+
| month | 700 and up | 600-699 | 500-599 | 499 and below | total |
+-------+------------+---------+---------+---------------+-------+
|     7 |          0 |       2 |       1 |             0 |     3 |
|     8 |          1 |       1 |       0 |             1 |     3 |
+-------+------------+---------+---------+---------------+-------+

此查询非常适合我们的小型结果集。但是,如果您将 4400 万行放入数据源表中,它就会停止运行。

有没有一种优化的方法来编写这个查询,可以实现我想要的,而不用把 mysql 挂上几天?

【问题讨论】:

    标签: mysql database dataset


    【解决方案1】:

    尝试解释选择...;

    这将告诉您查询是如何工作的。然后,您可以查看是否出于任何原因进行了全表扫描,并采取措施进行纠正。这可能包括 Cfreak 提出的建议。或者,在此处发布结果,我们将看看我们能做些什么。

    【讨论】:

      【解决方案2】:

      在值列上创建索引。

      create index value_index ON datasource(value)
      

      您应该只需要这样做一次。不过,它会稍微减慢您的插入速度。

      【讨论】:

        猜你喜欢
        • 2010-09-25
        • 1970-01-01
        • 1970-01-01
        • 2020-04-24
        • 2012-08-25
        • 1970-01-01
        • 1970-01-01
        • 2010-11-22
        • 2023-03-14
        相关资源
        最近更新 更多