2014-09-22 35 views
1

我正面臨着一個大數據問題。我有一個大的MySQL(Percona)表,每天加入一次,生產約250億行。我試圖將所有行組合在一起並聚合,以產生結果。查詢是一個簡單的加入:hadoop會比mySQL快嗎

--This query produces about 25 billion rows 
SELECT t1.colA as 'varchar(45)_1', t2.colB as 'varchar(45)_2', count(*) 
FROM table t1 
JOIN 
table t2 
on t1.date = t2.date 
GROUP BY t1.colA, t2.colB 

問題是這個過程需要一個多星期才能完成。我已經開始閱讀關於hadoop,並想知道map reduce功能是否可以提高處理數據的時間。我注意到HIVE是一個很好的附加組件,允許像hadoop這樣的SQL查詢。這一切看起來非常有前途,但我面對,我只在一臺機器上運行的一個問題:

6-core i7-4930K 
16GB RAM 
128 SSD 
2TB HDD 

當我運行與MySQL查詢,正在用我的資源大麥,只有約RAM 4GB的一個核心只有100%工作,另一個核心工作接近0%。我檢查了這一點,發現MySQL是單線程的。這也是爲什麼Hadoop看起來很有前途,因爲我注意到它可以運行多個映射器函數以更好地利用我的資源。我的問題仍然是在我可以在幾個小時內產生結果的情況下,hadoop能夠取代MySQL,儘管hadoop只會在單個節點上運行(儘管我知道它是用於分佈式計算的)。

+1

我只是想知道(不是你的問題的答案),但只是想知道在這裏......爲什麼需要這個結果集?這個結果集旨在回答什麼問題?這個查詢解決了什麼問題? (最有效的查詢是未運行的查詢。) – spencer7593 2014-09-22 19:28:14

+0

這是一個天氣數據集。在一個簡單的表格中,它會輸出一個位置在同一天的高低溫度上相同的次數(實際上它的數量比高低的要多一些,但它是它)。最後,我希望在同一天獲得所有具有相同高低溫度的地點(這將產生約250億個地點),並且希望得到結果集,哪些地方符合此條件的次數超過N次 – user2924127 2014-09-22 19:39:39

+0

您可能會檢查[Spark SQL](https://spark.apache.org/sql/)。在多個線程上運行羣集或單臺計算機。 – climbage 2014-09-22 23:22:20

回答

0

是的你是對的MySQL是單線程的,即每個查詢有1個線程。
只有1臺機器我不認爲它會對你有所幫助,因爲你可能會利用內核,但是由於所有的線程都會嘗試訪問磁盤,所以你將會爭用I/O。
你提到的行數很多,但你沒有提到磁盤上表的實際大小。
你的桌子有多大? (在HD上的字節數是我的意思)
另外你還沒有提到日期列是否被編入索引。 它可以幫助你,如果你刪除t2.colB或刪除所有GROUP BY在一起。
GROUP BY確實排序,在你的情況下它不好。你可以嘗試在你的應用程序中完成這個組。
也許你應該告訴我們你到底想要用你的查詢來達到什麼目的。可能有更好的方法來做到這一點。

+0

是表有索引,它使用內存引擎。當我將表格導出到csv時,大約需要2.5 GB的空間。我打算創建一個RamDisk來存儲hadoop可以讀取的csv。我忘了提到一些非常重要的東西,那就是我希望hadoop只輸出N個數更多的行(我估計95%的行將被刪除,並且它只會產生大約5%的行最後輸出中的行數可能會更少) – user2924127 2014-09-22 19:25:10

+0

我試着用使用TROVE hashmaps的java進行聚合,但是在大約100,000,000個入口進入映射之後,它們將具有嚴重的碰撞性能問題。 – user2924127 2014-09-22 19:27:23

+0

您正在使用內存存儲引擎嗎?這不是基於磁盤的存儲引擎。數據全部在內存中。如果你刪除了GROUP BY,它顯着更快? – Cratylus 2014-09-22 19:35:47

0

我有一個同樣大的查詢,並能夠利用所有的核心,把我的查詢拆分成多個小的並且同時運行它們。也許你也可以這樣做。您可以運行處理日期子集的兩個(或N個)查詢,並將結果寫入另一個表中,而不是處理所有日期的大型查詢。

也就是說,如果你的數據從2012年跨越到2013年

SELECT INTO myResults (colA,colB,colC) 
SELECT t1.colA as 'varchar(45)_1', t2.colB as 'varchar(45)_2', count(*) 
FROM table t1 
JOIN table t2 on t1.date = t2.date 
WHERE t1.date BETWEEN '2012-01-01' AND '2012-12-31' 
GROUP BY t1.colA, t2.colB 

SELECT INTO myResults (colA,colB,colC) 
SELECT t1.colA as 'varchar(45)_1', t2.colB as 'varchar(45)_2', count(*) 
FROM table t1 
JOIN table t2 on t1.date = t2.date 
WHERE t1.date BETWEEN '2013-01-01' AND '2013-12-31' 
GROUP BY t1.colA, t2.colB 
+0

我將不得不運行MySQL的多個實例以便能夠同時運行多個查詢,或者有另一種方式? – user2924127 2014-09-22 20:52:35

+0

@ user2924127您將只運行服務器的1個實例,但每個查詢都會(自動)產生自己的mysql進程 – FuzzyTree 2014-09-22 20:55:21

+0

今天晚些時候我會試一試,當您使用多個查詢運行查詢時是否有重大改進? – user2924127 2014-09-22 21:00:35

3

一些非常大的障礙了你會是Hadoop是真正的意思在集羣上運行,而不是一個單一的服務器。它可以使用多個內核,但它將消耗的資源量將非常重要。我有一個系統用於測試hadoop和hbase。它有namenode,secondary name節點,data node,nodemanager,resourcemanager,zookeeper等運行。這對單個系統來說是一個非常沉重的負擔。 Plus HIVE不是真正的SQL兼容的RDBMS替代品,因此它必須通過創建地圖/縮減作業來模擬一些工作。這些作業的磁盤密集程度要高得多,並且使用hdfs文件系統將數據映射到虛擬表(可能會有所不同)。由於文件系統應該分佈在很多系統上,因此HDFS也有相當大的開銷。

這樣說我不會推薦解決您的問題與Hadoop。我會建議檢查一下它在將來會提供什麼。

您是否研究過分割可以利用多個處理器的數據?恕我直言,這將是一個更清潔的解決方案。

http://www.percona.com/blog/2014/05/01/parallel-query-mysql-shard-query/

您也可以看看測試的Postgres。它具有非常好的內置並行查詢支持。

另一個想法是,您可以考慮嘗試使用olap cube來進行計算,並且可以即時重建索引,以便只有更改纔會生效。由於您確實在處理數據分析,因此這可能是一個理想的解決方案。

+0

Thank you for the great解釋爲什麼hadoop可能不是我的正確答案!我對OLAP完全陌生,但會閱讀它 – user2924127 2014-09-23 03:53:30

2

Hadoop不是一個神奇的子彈。

無論什麼是Hadoop中快於MySQL的主要是如何以及你的能力編寫Java代碼(Hadoop中映射器和減壓器)或SQL是一個問題...

通常情況下,Hadoop的閃耀,當你在單個主機上運行良好,需要同時將其擴展到100臺主機。如果你只有一臺電腦,它是而不是是最好的選擇;因爲它本質上是通過磁盤進行通信。寫入磁盤不是進行通信的最佳方式。它在分佈式系統中受歡迎的原因是崩潰恢復。但是,您無法從中受益:如果您丟失了單臺機器,即使使用Hadoop,也會失去一切。

相反:

  1. 弄清楚,如果你正在做正確的事情。沒有什麼比花時間去優化你不需要的計算更糟了。考慮一個子集的工作,首先要弄清楚你是否正在做正確的事情......(很有可能,首先你的查詢存在根本性的問題!)

  2. 優化你的SQL。使用多個查詢來分割工作負載。重複使用先前的結果,而不是再次計算它們。

  3. 減少你的數據。 預計返回250億的查詢必須預計會變慢!產生這種大小的結果只是非常低效。選擇一個不同的分析,並仔細檢查你是否做了正確的計算;因爲你很可能不是;但是你做了很多工作。

  4. 構建最佳分區。通過一些關鍵字對數據進行分區,並將每個日期放入單獨的表,數據庫,文件等等中。然後一次處理一個這樣的分區的連接(或者如果您的數據庫上有好的索引,只需查詢一個鍵一次)!