如何处理结构化的海量数据集? [关闭]
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');
我将这些表称为 logs
和 log_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 的原因,您的机器可能在查询期间响应速度很慢
当然,使用相关子查询将表连接到自身的幼稚方法可能会导致性能问题,这可以解释您的计算机“死机”的原因..以上是关于如何处理结构化的海量数据集? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章