2014-07-10 48 views
-2

我的問題是我通常沒有那麼大的數據。方法我已經使用了一些成功的小數據集扼殺了這個數據集,也許我的內存是不夠的。我需要處理MYSQL中的大數據集。下表中包含的數據大小爲10GB。我需要對它做一些具體的分析。如何處理結構化海量數據集?

我有兩個表,表1是如下,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 

表2是一種表

id type 
1 login 
2 change_budget 
3 search 

我需要分析活動之間的關係change_budget等活動。這是我迄今嘗試過的:

我嘗試爲每次一次寫入SQL的幫助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發生之前的一天內發生了多少次。

我的問題是我通常沒有那麼大的數據。如果我以與小數據相同的方式對待它,我的內存是不夠的。所以我需要一個大數據解決方案。任何建議?

注:我已經編輯了這個問題,試圖更好地解釋這個問題,但它仍然需要從原作者的審查,以驗證它正確地說明問題

+0

只寫代碼,你的想法... – user2963623

+0

@ user2963623顯然,如果OP知道怎麼寫,他不會尋求幫助的代碼...... –

+0

@ user2963623我的問題是我通常沒有那大數據。如果我以與小數據相同的方式對待它,我的內存是不夠的。所以我需要一個大數據解決方案。任何建議? – user3795071

回答

1

好,所以這裏有一些關於這個問題的東西,只是沒有道理......但是,你給這個工作的是我所做的。

FIRST:你的期望結果是完全不正確的..你說你想在它發生的那一天,但發佈一個完全不同的期望結果。我出去了一段時間,並假設你想要它,因爲這是要求,所以記住這是你會有的。

+-------------+---------+-----------+-----------+-----------+ 
|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在每一天發生的事情。

SECOND: 考慮到這一點,您可以通過幾種方式實現此查詢。其中最好的是製作臨時表來完成設置,然後再進行簡單的查詢。

設置:

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

0

看看dplyr。它的目的是顯式地允許您像使用數據框一樣處理數據庫表(子集,邏輯操作等),並允許您以SQL方式一個接一個地創建語句。

+0

我的問題是我通常沒有那麼大的數據。如果我以與小數據相同的方式對待它,我的內存是不夠的。所以我需要一個大數據解決方案。任何建議? – user3795071

+0

是的,你在你的問題中使用了這些確切的單詞。 Dplyr通過編寫聰明的查詢在sql方面進行了大量的分組和彙總。我懷疑它會爲你工作。 此外,請考慮將詳細文本字符串(「減少預算」)轉換爲單字節數字代碼(「2」)。 –

0

我理解這個問題的方法如下:

  1. 通過基於提取的日期數據以日期/時間字段中的數據集,提取日期
  2. 集團和幫助
  3. 分析文本列以查找單詞「增加/減少」的情況下,table2_id = 2
  4. 「pivot」的結果,所以分組數據是列中而不是行

下面的代碼就可以解決這個問題了一部分步驟4(可能包含語法錯誤,因爲我沒有MySQL的角落找尋,和日期/時間函數在不同的DBMS不同):

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

樞轉結果在MySQL似乎在下面的帖子回答: MySQL pivot table

評論:

  • 10GB是不是真的很大。爲了計算這個查詢,DBMS需要(最有可能的)group by(它基本上對前三列進行排序並對數據進行一次更多的掃描以進行實際的分組)。實際上假設(在這種情況下)一個記錄佔用50個字節,這意味着一個包含200M記錄的表=>排序成本是10GB以上的19個掃描(這將是一個相當不容忽視的估計),這意味着要掃描和寫入190GB數據。假設我們可以讀取/寫入50MB/s,整個查詢應該需要3800秒(非常低估)。實際上,我假設一些10GB÷50MB /秒= 200秒的執行時間

  • 該查詢似乎是一個相當簡單的數據選擇/聚合查詢。我建議閱讀一本關於SQL的書籍以更多地瞭解它。您可能只需要閱讀前幾頁來了解它

  • https://dba.stackexchange.com/對於這類問題似乎更爲合適。但是考慮問題的簡單,答案不是很多人可能會覺得很有趣,足以回答這個問題:)

我的問題是我通常不會有大的數據。如果我像 一樣處理小數據,我的內存是不夠的。所以我需要一個 大數據解決方案。任何建議?

DBMS是智能系統。他們檢查你有多少內存,並尋找快速解決你的查詢。在你的情況下,如果RAM的數量是MM比10GB低很多,那麼DBMS會將你的數據切分成N<M數據塊,在RAM中對這些塊進行排序,保存到磁盤,然後進行分類合併,導致很多更快的解決方案

+0

我認爲他知道他通常可以做到這一點,但這種解決方案是爲他的記憶密集型 – Eknoes

+0

感謝您的回答。我寫的SQL讓我的電腦死機......也許原因不是數據太大,只是我無法寫入SQL。 – user3795071

+0

您可能想要創建一個更小的表格(比如說大約10000行)。做一些類似的事情:'在表1中創建小於select *的表,其中「data」 arthur