天天看點

Hive 中的四種排序詳解,再也不會混淆用法了

Hive表的基本操作 Hive中的集合資料類型 Hive動态分區詳解 hive中orc格式表的資料導入 Java通過jdbc連接配接hive 通過HiveServer2通路Hive SpringBoot連接配接Hive實作自助取數 hive關聯hbase表 Hive udf 使用方法 Hive基于UDF進行文本分詞 Hive視窗函數row number的用法 資料倉庫之拉連結清單
關注公衆号:<code>大資料技術派</code>,回複: <code>資料</code>,領取<code>1024G</code>資料。

排序操作是一個比較常見的操作,尤其是在資料分析的時候,我們往往需要對資料進行排序,hive 中和排序相關的有四個關鍵字,今天我們就看一下,它們都是什麼作用。

Hive 中的四種排序詳解,再也不會混淆用法了

下面我們有一份溫度資料,tab 分割

建表加載資料

order by會對輸入做全局排序,是以隻有一個Reducer(多個Reducer無法保證全局有序),然而隻有一個reducer,會導緻當輸入規模較大時,消耗較長的計算時間

降序:desc

升序:asc 不需要指定,預設是升序

需要注意的是它受<code>hive.mapred.mode</code>的影響,在嚴格模式下,必須使用limit 對排序的資料量進行限制,因為資料量很大隻有一個reducer的話,會出現OOM 或者運作時間超長的情況,是以嚴格模式下,不适用limit 則會報錯,更多請參考Hive的嚴格模式和本地模式

接下來我們看一下order by的排序結果<code>select * from ods_temperature order by year;</code>

Hive 中的四種排序詳解,再也不會混淆用法了

不是全局排序,其在資料進入reducer前完成排序,也就是說它會在資料進入reduce之前為每個reducer都産生一個排序後的檔案。是以,如果用sort by進行排序,并且設定mapreduce.job.reduces&gt;1,則sort by隻保證每個reducer的輸出有序,不保證全局有序。

它不受Hive.mapred.mode屬性的影響,sort by的資料隻能保證在同一個reduce中的資料可以按指定字段排序。使用sort by你可以指定執行的reduce個數(通過set mapred.reduce.tasks=n來指定),對輸出的資料再執行歸并排序,即可得到全部結果。

Hive 中的四種排序詳解,再也不會混淆用法了

發現上面的輸出好像看不出來啥,隻能看到不是有序的,哈哈,那我們換一種方法,将資料輸出到檔案,因為我們設定了reduce數是3,那應該會有三個檔案輸出

Hive 中的四種排序詳解,再也不會混淆用法了

可以看出這下就清楚多了,我們看到一個分區内的年份并不同意,那個年份的資料都有

首先我們看一個現象,一般情況下我們認為sort by 應該是比 order by 快的,因為 order by 隻能使用一個reducer,進行全部排序,但是當資料量比較小的時候就不一定了,因為reducer 的啟動耗時可能遠遠資料處理的時間長,就像下面的例子order by 是比sort by快的

Hive 中的四種排序詳解,再也不會混淆用法了

可以在sort by 用limit子句減少資料量,使用limit n 後,傳輸到reduce端的資料記錄數就減少到 n *(map個數),也就是說我們在sort by 中使用limit 限制的實際上是每個reducer 中的數量,然後再根據sort by的排序字段進行order by,最後傳回n 條資料給用戶端,也就是說你在sort by 用limit子句,最後還是會使用order by 進行最後的排序

order by 中使用limit 是對排序好的結果檔案去limit 然後交給reducer,可以看到sort by 中limit 子句會減少參與排序的資料量,而order by 中的不行,隻會限制傳回用戶端資料量的多少。

從上面的執行效率,我們看到sort by limit 幾乎是 order by limit 的兩倍了 ,大概才出來應該是多了某個環節

Hive 中的四種排序詳解,再也不會混淆用法了

接下來我們分别看一下order by limit 和 sort by limit 的執行計劃

<code>explain select * from ods_temperature order by year limit 2;</code>

Hive 中的四種排序詳解,再也不會混淆用法了

<code>explain select * from ods_temperature sort by year limit 2;</code>

Hive 中的四種排序詳解,再也不會混淆用法了

從上面截圖我圈出來的地方可以看到

sort by limit 比 order by limit 多出了一個stage(order limit)

sort by limit 實際上執行了兩次limit ,減少了參與排序的資料量

distribute by是控制在map端如何拆分資料給reduce端的。類似于MapReduce中分區partationer對資料進行分區

hive會根據distribute by後面列,将資料分發給對應的reducer,預設是采用hash算法+取餘數的方式。

sort by為每個reduce産生一個排序檔案,在有些情況下,你需要控制某寫特定的行應該到哪個reducer,這通常是為了進行後續的聚集操作。distribute by剛好可以做這件事。是以,distribute by經常和sort by配合使用。

例如上面的sort by 的例子中,我們發現不同年份的資料并不在一個檔案中,也就說不在同一個reducer 中,接下來我們看一下如何将相同的年份輸出在一起,然後按照溫度升序排序

首先我們嘗試一下沒有distribute by 的SQL的實作

Hive 中的四種排序詳解,再也不會混淆用法了

發現結果并沒有把相同年份的資料配置設定在一起,接下來我們使用一下distribute by

Hive 中的四種排序詳解,再也不會混淆用法了

這下我們看到相同年份的都放在了一下,可以看出2013 和 2016 放在了一起,但是沒有一定順序,這個時候我們可以對 distribute by 字段再進行一下排序

Hive 中的四種排序詳解,再也不會混淆用法了

cluster by除了具有distribute by的功能外還兼具sort by的功能。但是排序隻能是升序排序,不能指定排序規則為ASC或者DESC。

當分區字段和排序字段相同cluster by可以簡化distribute by+sort by 的SQL 寫法,也就是說當distribute by和sort by 字段相同時,可以使用cluster by 代替distribute by和sort by

Hive 中的四種排序詳解,再也不會混淆用法了
Hive 中的四種排序詳解,再也不會混淆用法了

我們看到上面兩種SQL寫法的輸出結果是一樣的,這也就證明了我們的說法,當distribute by和sort by 字段相同時,可以使用cluster by 代替distribute by和sort by

當你嘗試給cluster by 指定排序方向的時候,你就會得到如下錯誤。

order by 是全局排序,可能性能會比較差;

sort by分區内有序,往往配合distribute by來确定該分區都有那些資料;

distribute by 确定了資料分發的規則,滿足相同條件的資料被分發到一個reducer;

cluster by 當distribute by和sort by 字段相同時,可以使用cluster by 代替distribute by和sort by,但是cluster by預設是升序,不能指定排序方向;

sort by limit 相當于每個reduce 的資料limit 之後,進行order by 然後再limit ;

繼續閱讀