如何处理结构化的海量数据集? [关闭]

Posted

技术标签:

【中文标题】如何处理结构化的海量数据集? [关闭]【英文标题】:How to deal with structured massive dataset? [closed] 【发布时间】:2014-07-10 20:35:46 【问题描述】:

我的问题是我通常没有那么大的数据。当小数据集阻塞在这个数据集上时,我使用的方法取得了一些成功,也许我的内存不够用。我需要处理 mysql 中的大型数据集。如下表,包含大至 10gb 的数据。我需要对它做一些具体的分析。

我有两张表,table1如下,id为主键,table2_id为外键

id date                 aid table2_id message
1  2014-03-19 16:21:02  121   1       login from xxxx
2  2014-03-20 14:00:32  123   2       decrease budget
3  2014-03-20 18:00:32  121   2       increase budget
4  2014-03-21 16:21:02  121   3       login from xxxx
5  2014-03-21 16:21:02  121   3       login from xxxx
6  2014-03-22 10:21:02  121   2       increase budget

table2 是一个类型表

id type
1  login
2  change_budget
3  search

我需要分析活动 change_budget 与其他活动之间的关系。这是我迄今为止尝试过的方法:

我尝试为每次一个辅助 change_budget 编写 SQL,计算该辅助在前 24 小时内的所有其他操作。如果一个援助在 2014-03-14 16:21:02 有一个 change_budget,我需要从 2014-03-13 16:21:02 到 2014-03-14 16:21:02 对此援助执行的所有操作。然后,按动作分组并计算我想要的结果应该如下所示。

aid login search change_budget
121 1     0      1
123 0     0      -1
121 0     2      1 

-1 表示 change_budget 减少,1 表示增加。 其他数字是在此援助 change_budget 发生前一天内此援助的此操作发生了多少次。

我的问题是我通常没有那么大的数据。如果我以与小数据相同的方式对待它,我的 ram 是不够的。所以我需要一个大数据解决方案。有什么建议吗?

注意:我已经编辑了这个问题,试图更好地解释这个问题,但它仍然需要原作者的审查,以验证它是否正确地说明了问题

【问题讨论】:

只需为您的想法编写代码... @user2963623 显然,如果 OP 知道如何编写代码,他就不会寻求帮助... @user2963623 我的问题是我通常没有那么大的数据。如果我以与小数据相同的方式对待它,我的 ram 是不够的。所以我需要一个大数据解决方案。有什么建议吗? @user3795071 你可以做的一件事是在你的 localhost 机器甚至是 sqlfiddle 上制作你的表的一个小版本,然后使用一个更小的数据集...... 大数据需要时间来处理。每当我处理这些事情时,我都会让我的电脑开上几个小时甚至几天!如果有帮助,你可能想看看多线程 【参考方案1】:

好的,所以关于这个问题的一些事情是没有意义的......但是,你所付出的努力就是我所做的。

第一:你想要的结果是完全不正确的。你说你想要它发生的那一天,但发布了一个完全不同的想要的结果。我不顾一切地假设你想要它,因为这是要求的,所以考虑到这就是你想要的。

+-------------+---------+-----------+-----------+-----------+
|day occurred | aid     | logins    | searches  | budget    |
+-------------+---------+-----------+-----------+-----------+
|'2014-03-19' | 121     |   1       |   0       |   0       |
|'2014-03-20' | 123     |   0       |   0       |   -1      |
|'2014-03-20' | 121     |   0       |   0       |   1       |
|'2014-03-21' | 121     |   0       |   2       |   0       |
|'2014-03-22' | 121     |   0       |   0       |   1       |
+-------------+---------+-----------+-----------+-----------+

这是来自您提供的数据...这是每个 AID 每天发生的情况。

第二次: 考虑到这一点,您可以通过几种方式实现此查询。其中最好的是制作临时表来进行设置,然后对它们进行简单的查询。

设置:

CREATE TABLE logs
    (`id` int, `date` datetime, `aid` int, `t2_id` int, `message` varchar(55))
;

INSERT INTO logs
    (`id`, `date`, `aid`, `t2_id`, `message`)
VALUES
(1,  '2014-03-19 16:21:02',  121,   1,       'login from xxxx'),
(2,  '2014-03-20 14:00:32',  123,   2,       'decrease budget'),
(3,  '2014-03-20 18:00:32',  121,   2,       'increase budget'),
(4,  '2014-03-21 16:21:02',  121,   3,       'login from xxxx'),
(5,  '2014-03-21 16:21:02',  121,   3,       'login from xxxx'),
(6,  '2014-03-22 10:21:02',  121,   2,       'increase budget')
;


CREATE TABLE log_type
    (`id` int, `type` varchar(55))
;

INSERT INTO log_type
    (`id`, `type`)
VALUES
(1,  'login'),
(2,  'change_budget'),
(3,  'search');

我将这些表称为 logslog_type,因为这似乎是这里发生的事情。这些表正在记录交互。

临时表:

CREATE TEMPORARY TABLE t1
(
    SELECT
        l.aid,
        DATE(date) AS grouping_col,
        IF(
            lt.type = 'change_budget', 
                IF(l.message LIKE '%decrease%', -1, 1), 
                0
        ) AS changed_budget
    FROM logs l 
    JOIN log_type lt ON lt.id = l.t2_id
    GROUP BY grouping_col, changed_budget, aid
);

CREATE TEMPORARY TABLE t2
(   SELECT
        DATE(l.date) AS grouping_col,
        l.aid,
        IF(lt.type = 'login', COUNT(l.id), 0) AS logged_in
    FROM logs l 
    JOIN log_type lt ON lt.id = l.t2_id
    GROUP BY grouping_col,  aid
); 

CREATE TEMPORARY TABLE t3
 (
    SELECT
        DATE(l.date) AS grouping_col,
        l.aid,
        IF(lt.type = 'search', COUNT(l.id), 0) AS searched_for
    FROM logs l 
    JOIN log_type lt ON lt.id = l.t2_id
    GROUP BY grouping_col, aid
);

最终查询:

最后,您需要做的就是查询这些临时表以获得您想要的结果

SELECT 
    t1.grouping_col as day_occurred, 
    t1.aid, 
    logged_in, 
    searched_for, 
    changed_budget 
FROM t1
JOIN t2 on t2.grouping_col = t1.grouping_col AND t2.aid = t1.aid
JOIN t3 on t3.grouping_col = t1.grouping_col AND t3.aid = t1.aid
;

结果:

我在我的本地主机数据库上设置并运行它,结果就是它应该是的。 IMAGE

【讨论】:

【参考方案2】:

看看 dplyr。它旨在明确允许您将数据库表视为数据框(子集、逻辑操作等),并允许您以 SQL 式的方式一个接一个地构建语句。

【讨论】:

我的问题是我通常没有那么大的数据。如果我以与小数据相同的方式对待它,我的 ram 是不够的。所以我需要一个大数据解决方案。有什么建议吗? 是的,您在问题中使用了这些确切的词。 Dplyr 通过编写巧妙的查询在 sql 端做了很多分组和求和。我怀疑它会为你工作。另外,考虑将冗长的文本字符串(“减少预算”)翻译成单字节数字代码(“2”)。【参考方案3】:

我理解问题的方式如下:

    获取数据集的日期/时间字段,提取日期 根据提取的日期和辅助数据按数据分组 分析文本列以查找单词“increase/decrease”以防 table2_id = 2 “透视”结果,因此分组数据在列中而不是在行中

下面的代码应该可以解决步骤4之前的部分问题(可能包含语法错误,因为我没有mysql arround,并且不同DBMS中的日期/时间函数不同):

select date("date"), aid, table2_id, count(message)
from table1
group by date("date"), aid, table2_id

在 MySQL 中旋转结果似乎在以下帖子中得到了回答: MySQL pivot table

评论:

10GB 并不是很大。为了计算这个查询,DBMS 需要(很可能)分组(基本上是对前三列执行排序,然后再扫描一次数据以进行实际分组)。实际假设(在这种情况下)一条记录占用 50 个字节,这意味着一个有 200M 记录的表 => 排序成本是 19 次扫描超过 10GB(这将是一个相当悲观的估计),这意味着要扫描和写入 190GB 的数据。假设我们可以读/写 50MB/s,整个查询应该需要 3800 秒(非常悲观的估计)。实际上,我假设大约 10GB ÷ 50MB/s = 200 秒的执行时间

查询似乎是一个相当简单的数据选择/聚合查询。我建议阅读有关 SQL 的书以了解更多信息。您可能只需要阅读前几十页即可了解它

https://dba.stackexchange.com/ 似乎更适合这类问题。但是考虑到问题的简单性和答案,可能没有多少人会觉得它足够有趣来回答它:)

我的问题是我通常没有那么大的数据。如果我对待它 和小数据一样,我的内存也不够用。所以我需要一个 大数据解决方案。有什么建议吗?

DBMS 是智能系统。他们检查您有多少 RAM,并为您的查询寻找快速解决方案。在您的情况下,如果 RAM 的数量是 M 并且 M 远低于 10GB,那么 DBMS 会将您的数据切分成 N<M 数据块,在 RAM 中对这些块进行排序,将其保存到磁盘,然后之后进行排序合并,从而获得更快的解决方案

【讨论】:

我认为他知道他通常如何做到这一点,但这种解决方案对他来说是内存密集型 感谢您的回答。我写的SQL让我的电脑死机了……可能不是数据太大,只是我不会写SQL。 您可能想要创建一个较小的表(比如一开始有 10000 行)来玩。执行以下操作:create table smaller as select * from table1 where "data" < some_date(例如限制 10000),然后在较小的东西上运行 SQL 查询。这可能会更少地“杀死”您的计算机。完成后,让您的机器运行大型查询。请记住,由于 I/O 的原因,您的机器可能在查询期间响应速度很慢 当然,使用相关子查询将表连接到自身的幼稚方法可能会导致性能问题,这可以解释您的计算机“死机”的原因..

以上是关于如何处理结构化的海量数据集? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

如何处理海量数据

海量日志数据如何处理统计?

如何处理海量数据查询并将时间控制在1秒以内?

数据集

在线文本实体抽取能力,助力应用解析海量文本数据

SQL如何快速处理海量数据?