1. 程式人生 > >Hive SQL優化之 Count Distinct

Hive SQL優化之 Count Distinct

Hive是Hadoop的子專案,它提供了對資料的結構化管理和類SQL語言的查詢功能。SQL的互動方式極大程度地降低了Hadoop生態環境中資料處理的門檻,使用者不需要編寫程式,通過SQL語句就可以對資料進行分析和處理。目前很多計算需求都可以由Hive來完成,極大程度地降低了開發成本。

目前,Hive底層使用MapReduce作為實際計算框架,SQL的互動方式隱藏了大部分MapReduce的細節。這種細節的隱藏在帶來便利性的同時,也對計算作業的調優帶來了一定的難度。未經優化的SQL語句轉化後的MapReduce作業,它的執行效率可能大大低於使用者的預期。本文我們就來分析一個簡單語句的優化過程。

日常統計場景中,我們經常會對一段時期內的欄位進行消重並統計數量,SQL語句類似於

SELECT COUNT( DISTINCT id ) FROM TABLE_NAME WHERE ...;

這條語句是從一個表的符合WHERE條件的記錄中統計不重複的id的總數。

該語句轉化為MapReduce作業後執行示意圖如下,圖中還列出了我們實驗作業中Reduce階段的資料規模:
Hive process 1
由於引入了DISTINCT,因此在Map階段無法利用combine對輸出結果消重,必須將id作為Key輸出,在Reduce階段再對來自於不同Map Task、相同Key的結果進行消重,計入最終統計值。
我們看到作業執行時的Reduce Task個數為1,對於統計大資料量時,這會導致最終Map的全部輸出由單個的ReduceTask處理。這唯一的Reduce Task需要Shuffle大量的資料,並且進行排序聚合等處理,這使得它成為整個作業的IO和運算瓶頸。
經過上述分析後,我們嘗試顯式地增大Reduce Task個數來提高Reduce階段的併發,使每一個Reduce Task的資料處理量控制在2G左右。具體設定如下:

set mapred.reduce.tasks=100

調整後我們發現這一引數並沒有影響實際Reduce Task個數,Hive執行時輸出“Number of reduce tasks determined at compile time: 1”。原來Hive在處理COUNT這種“全聚合(full aggregates)”計算時,它會忽略使用者指定的Reduce Task數,而強制使用1。我們只能採用變通的方法來繞過這一限制。我們利用Hive對巢狀語句的支援,將原來一個MapReduce作業轉換為兩個作業,在第一階段選出全部的非重複id,在第二階段再對這些已消重的id進行計數。這樣在第一階段我們可以通過增大Reduce的併發數,併發處理Map輸出。在第二階段,由於id已經消重,因此COUNT(*)操作在Map階段不需要輸出原id資料,只輸出一個合併後的計數即可。這樣即使第二階段Hive強制指定一個Reduce Task,極少量的Map輸出資料也不會使單一的Reduce Task成為瓶頸。改進後的SQL語句如下:

SELECT COUNT(*) FROM (SELECT DISTINCT id FROM TABLE_NAME WHERE … ) t;

實際執行時,我們發現Hive還對這兩階段的作業做了額外的優化。它將第二個MapReduce作業Map中的Count過程移到了第一個作業的Reduce階段。這樣在第一階Reduce就可以輸出計數值,而不是消重的全部id。這一優化大幅地減少了第一個作業的Reduce輸出IO以及第二個作業Map的輸入資料量。最終在同樣的執行環境下優化後的語句執行只需要原語句20%左右的時間。優化後的MapReduce作業流如下:

Hive process 2

從上述優化過程我們可以看出,一個簡單的統計需求,如果不理解Hive和MapReduce的工作原理,它可能會比優化後的執行過程多四、五倍的時間。我們在利用Hive簡化開發的同時,也要儘可能優化SQL語句,提升計算作業的執行效率。

注:文中測試環境Hive版本為0.9

相關推薦

Hive SQL優化 Count Distinct

Hive是Hadoop的子專案,它提供了對資料的結構化管理和類SQL語言的查詢功能。SQL的互動方式極大程度地降低了Hadoop生態環境中資料處理的門檻,使用者不需要編寫程式,通過SQL語句就可以對資料進行分析和處理。目前很多計算需求都可以由Hive來完成,極大程度地降低

SQL優化count(*),count(l列)

一、count各種用法的區別 1、count函式是日常工作中最常用的函式之一,用來統計表中資料的總數,常用的有count(*),count(1),count(列)。count(*)和count(1)是用來統計表中共有多少資料。是針對全表的 1 SELECT COUNT(*) FROM TAB1; 2

sql優化count(distinct xxxx)

select count(distinct   column) from table_name; 這樣一條sql在資料量比較大時可能跑的時間很長。 可以用:select count(1) from (select   column from table_name group

MySQL SQL優化‘%’

sql優化設計索引的主要目的就是幫助我們快速獲取查詢結果,而以%開頭的like查詢則不能夠使用B-Tree索引。考慮到innodb的表都是聚簇表(類似於oracle中的索引組織表),且二級索引葉節點中記錄的結構為(索引字段->主鍵字段),我們可以通過改寫sql(mysql優化器比較笨,需要給它足夠的提示

3.SQL優化SELECT語句

介紹 資料庫應用程式的核心邏輯是通過SQL語句執行的,無論是直接通過直譯器發出還是通過API在幕後提交。所以優化SQL語句是優化資料庫的重中之重。 1 優化SELECT語句 SELECT調優不光適用於以SELECT開始的SQL語句,也適用於DELETE語句中的CREATE TAB

4.SQL優化Where語句

1 優化Where語句 以下優化適用於使用SELECT語句,但相同的優化適用於DELETE和UPDATE語句中的WHERE子句。 為了優化查詢,有時我們可能考慮犧牲程式可讀性,但是MySQL在生成執行計劃時會對SQL進行改寫,所以我們不需要過度改寫,儘量保證可讀性,只有在效能無法滿足

hive 引數優化hive.auto.convert.join

Total MapReduce jobs = 1 14/08/24 20:29:11 WARN conf.Configuration: mapred.max.split.size is deprecated. Instead, use mapreduce.input.fileinputforma

(ainusers轉載優秀文章)SQL優化my.cnf

[client] default-character-set=utf8mb4 #mysqlde utf8字符集預設為3位的,不支援emoji表情及部分不常見的漢字,故推薦使用utf8mb4   [mysql] default-character-set=utf8mb4   [my

SQL優化limit 1

  在某些情況下,如果明知道查詢結果只有一個,SQL語句中使用LIMIT 1會提高查詢效率。   例如下面的使用者表(主鍵id,郵箱,密碼):  1 create table t_user( 2   id int primary key auto_increment, 3

sql優化in與

在我們開發過程中,初期可能不會去太關注我們自己寫的sql語句的效率怎麼樣,因為總是覺得可以拿取到資料就算是ok了,可能也會注意一下你的sql執行的時間,但是在開發的過程中因為資料量的原因,其實你不去了解一下sql的一些優化的手段其實是無法感知你的sql的效率問題

讓天下沒有難用的資料庫 » mysql sql優化straight_join

在oracle中可以指定的表連線的hint有很多:ordered hint 指示oracle按照from關鍵字後的表順序來進行連線;leading hint 指示查詢優化器使用指定的表作為連線的首表,即驅動表;use_nl hint指示查詢優化器使用nested loops方式連線指定表和其他行源,

讓天下沒有難用的資料庫 » MySql sql優化order by desc/asc limit M

Order by desc/asc limit M是我在mysql sql優化中經常遇到的一種場景,其優化原理也非常的簡單,就是利用索引的有序性,優化器沿著索引的順序掃描,在掃描到符合條件的M行資料後,停止掃描;看起來非常的簡單,但是我經常看到很多效能較差的sql沒有利用這個優化規律,下面將結合一些

MySQL SQL優化覆蓋索引

內容概要 利用主索引提升SQL的查詢效率是我們經常使用的一個技巧,但是有些時候MySQL給出的執行計劃卻完全出乎我們的意料,我們預想MySQL會通過索引掃描完成查詢,但是MySQL給出的執行計劃卻是通過全表掃描完成查詢的,其中的某些場景我們可以利用覆蓋索引進行優化。

sql優化資料庫新增索引

索引作用在索引列上,除了上面提到的有序查詢之外,資料庫利用各種各樣的快速定位技術,能夠大大提高查詢效率。特別是當資料量非常大,查詢涉及多個表時,使用索引往往能使查詢速度加快成千上萬倍。例如,有3個未索引的表t1、t2、t3,分別只包含列c1、c2、c3,每個表分別含有1000行資料組成,指為1~1000的數值

資料庫優化SQL優化SELECT優化 ——group by 優化

在資料庫查詢中,group by語句經常使用,而這個語句的使用是最耗效能的,按常理, 我們生活中要這樣做也很麻煩,有兩種情形:         1、有索引的情況         2、無索引的情況 對於第一種情況,如果在生活中要做這樣的事情,很惱火,我們正常的想法是,先把所有

資料庫優化SQL優化SELECT優化 ——JOIN和LEFT JOIN 和 RIGHT JOIN

         在資料庫的應用中,我們經常需要對多表進行連表操作來獲得關係型的資料,因此,應該更加的掌握好 SQL語句的join原理,因為,可以稍一不慎,可能一個不好的join導致資料庫的全表掃描,查詢出大量的 無用的資訊,並且對資料庫效能影響極大。          資

SQL優化索引

SQL優化有很多方法,今天來說一說資料庫索引。 舉例說明:  假設有一個圖書Book表,裡面有欄位id,name, isbn等。如果圖書數量巨大的話,我們通過isbn查詢通常是比較慢的。  新增索引:  create index index_isbn ON book

MySQL查詢優化COUNT()

COUNT()聚合函式,以及如何優化使用了該函式的查詢,很可能是MySQL中最容易被誤解的前10個話題之一,在網上隨便搜尋一下就能看到很多錯誤的理解,可能比我們想象的多得多。 在做優化之前,先來看看COUNT()函式的真正作用是什麼。 COUNT()的作

sql優化(DMV)

Microsoft SQL Server 2005 提供了一些工具來監控資料庫。方法之一是動態管理檢視。動態管理檢視 (DMV) 和動態管理函式 (DMF) 返回的伺服器狀態資訊可用於監控伺服器例項的執行狀況、診斷問題和優化效能。 常規伺服器動態管理物件包括: dm_db_*:資料庫和資料庫物

MySQL SQL優化 執行計劃 explain

1.環境 OS: CentOS 6.5 x64 MySQL: 5.6 for Linux (x86_64) 2.優化第一步 拿到一個慢SQL時,第一步就是看執行計劃並權衡是否可以加索引,就是這麼簡單,不要被高深莫測的人給矇住說什麼有更好的方