寫入時(shí)間戳類型數(shù)據(jù)到Parquet担锤,再用Impala讀取

Parquet是一種新型列存儲(chǔ)格式,它可以兼容Hadoop生態(tài)圈中大多數(shù)計(jì)算框架(Hadoop乍钻、Spark等)肛循,被多種查詢引擎支持(Hive、Impala银择、Drill等)多糠,并且它是語(yǔ)言和平臺(tái)無關(guān)的。Parquet最初是由Twitter和Cloudera(由于Impala的緣故)合作開發(fā)完成并開源浩考,2015年5月從Apache的孵化器里畢業(yè)成為Apache頂級(jí)項(xiàng)目[1][2]夹孔。
用Java讀寫Parquet格式文件需要以下maven依賴:

<dependency>
    <groupId>org.apache.parquet</groupId>
    <artifactId>parquet-column</artifactId>
    <version>1.8.2</version>
</dependency>
<dependency>
    <groupId>org.apache.parquet</groupId>
    <artifactId>parquet-common</artifactId>
    <version>1.8.2</version>
</dependency>
<dependency>
    <groupId>org.apache.parquet</groupId>
    <artifactId>parquet-encoding</artifactId>
    <version>1.8.2</version>
</dependency>
<dependency>
    <groupId>org.apache.parquet</groupId>
    <artifactId>parquet-hadoop</artifactId>
    <version>1.8.2</version>
</dependency>

下面是寫入parquet文件說明和關(guān)鍵代碼:
Date、Timestamp類型需要保存為int96析孽,否則impala讀取出錯(cuò)搭伤。
int96為12字節(jié),前8字節(jié)表示時(shí)間戳對(duì)應(yīng)當(dāng)天已過去的納秒數(shù)袜瞬,后4字節(jié)表示時(shí)間戳當(dāng)天距離儒略歷起始日已過去的天數(shù)怜俐。
注意前8字節(jié)和后4字節(jié)都是小端字節(jié)序,如果寫入時(shí)使用大端序?qū)?dǎo)致讀取失敗[3][4]邓尤。

    // schema定義
    ...
    required int96 timestamp_field;
    ...
    public static byte[] getBytes(int i) {
        byte[] bytes=new byte[4];
        bytes[0]=(byte)((i >> 24) & 0xFF);
        bytes[1]=(byte)((i >> 16) & 0xFF);
        bytes[2]=(byte)((i >> 8) & 0xFF);
        bytes[3]=(byte)(i & 0xFF);
        return bytes;
    }

    public static byte[] getBytes(long i) {
        byte[] bytes=new byte[8];
        bytes[0]=(byte)((i >> 56) & 0xFF);
        bytes[1]=(byte)((i >> 48) & 0xFF);
        bytes[2]=(byte)((i >> 40) & 0xFF);
        bytes[3]=(byte)((i >> 32) & 0xFF);
        bytes[4]=(byte)((i >> 24) & 0xFF);
        bytes[5]=(byte)((i >> 16) & 0xFF);
        bytes[6]=(byte)((i >> 8) & 0xFF);
        bytes[7]=(byte)(i & 0xFF);
        return bytes;
    }

    // 調(diào)轉(zhuǎn)字節(jié)數(shù)組
    public static void flip(byte[] bytes) {
        for(int i=0,j=bytes.length-1;i<j;i++,j--) {
              byte t=bytes[i];
              bytes[i]=bytes[j];
              bytes[j]=t;
        }
    }

    // 每天的納秒數(shù)
    private static final long NANO_SECONDS_PER_DAY = 86400_000_000_000L;
    // 儒略歷起始日(儒略歷的公元前4713年1月1日中午12點(diǎn)拍鲤,在格里歷是公元前4714年11月24日)距離1970-01-01的天數(shù)
    private static final long JULIAN_EPOCH_OFFSET_DAYS = 2440588;

    // 寫入數(shù)據(jù)贴谎,此處預(yù)先存在一個(gè)Date對(duì)象(可由時(shí)間戳轉(zhuǎn)換得到)
    Date date = ...
    // 轉(zhuǎn)換成距1970-01-01 00:00:00的納秒數(shù)
    long nano = date.getTime() * 1000_000;
    // 轉(zhuǎn)換成距儒略歷起始日的天數(shù)
    int julianDays = (int) ((nano / NANO_SECONDS_PER_DAY) + JULIAN_EPOCH_OFFSET_DAYS);
    byte[] julianDaysBytes = getBytes(julianDays);
    flip(julianDaysBytes);
    // 當(dāng)前時(shí)間戳距離當(dāng)天已過去的納秒數(shù)
    long lastDayNanos = nano % NANO_SECONDS_PER_DAY;
    byte[] lastDayNanosBytes = getBytes(lastDayNanos);
    flip(lastDayNanosBytes);
    byte[] dst = new byte[12];
    // 前8字節(jié)表示時(shí)間戳對(duì)應(yīng)當(dāng)天已過去的納秒數(shù)
    System.arraycopy(lastDayNanosBytes, 0, dst, 0, 8);
    // 后4字節(jié)表示時(shí)間戳當(dāng)天距離儒略歷起始日已過去的天數(shù)
    System.arraycopy(julianDaysBytes, 0, dst, 8, 4);
    // Group group = factory.newGroup();
    group.append("timestamp_field", Binary.fromConstantByteArray(dst));

這樣寫入parquet文件后,Impala將可以正確讀取對(duì)應(yīng)字段的內(nèi)容季稳。

參考:
[1] https://parquet.apache.org/
[2] Parquet格式詳解:https://blog.csdn.net/yu616568/article/details/50993491
[3] NanosecondsToImpalaTimestamp函數(shù):https://github.com/apache/parquet-cpp/blob/master/src/parquet/arrow/writer.h
[4] Github關(guān)于INT96的討論:https://github.com/apache/parquet-format/pull/49

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末赴精,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子绞幌,更是在濱河造成了極大的恐慌蕾哟,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,607評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件莲蜘,死亡現(xiàn)場(chǎng)離奇詭異谭确,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)票渠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,239評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門逐哈,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人问顷,你說我怎么就攤上這事昂秃。” “怎么了杜窄?”我有些...
    開封第一講書人閱讀 164,960評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵肠骆,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我塞耕,道長(zhǎng)蚀腿,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,750評(píng)論 1 294
  • 正文 為了忘掉前任扫外,我火速辦了婚禮莉钙,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘筛谚。我一直安慰自己磁玉,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,764評(píng)論 6 392
  • 文/花漫 我一把揭開白布驾讲。 她就那樣靜靜地躺著蚊伞,像睡著了一般。 火紅的嫁衣襯著肌膚如雪蝎毡。 梳的紋絲不亂的頭發(fā)上厚柳,一...
    開封第一講書人閱讀 51,604評(píng)論 1 305
  • 那天氧枣,我揣著相機(jī)與錄音沐兵,去河邊找鬼。 笑死便监,一個(gè)胖子當(dāng)著我的面吹牛扎谎,可吹牛的內(nèi)容都是我干的碳想。 我是一名探鬼主播,決...
    沈念sama閱讀 40,347評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼毁靶,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼胧奔!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起预吆,我...
    開封第一講書人閱讀 39,253評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤龙填,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后拐叉,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體岩遗,經(jīng)...
    沈念sama閱讀 45,702評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,893評(píng)論 3 336
  • 正文 我和宋清朗相戀三年凤瘦,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了宿礁。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,015評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡蔬芥,死狀恐怖梆靖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情笔诵,我是刑警寧澤返吻,帶...
    沈念sama閱讀 35,734評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站乎婿,受9級(jí)特大地震影響思喊,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜次酌,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,352評(píng)論 3 330
  • 文/蒙蒙 一恨课、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧岳服,春花似錦剂公、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,934評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至璃搜,卻和暖如春拖吼,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背这吻。 一陣腳步聲響...
    開封第一講書人閱讀 33,052評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工吊档, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人唾糯。 一個(gè)月前我還...
    沈念sama閱讀 48,216評(píng)論 3 371
  • 正文 我出身青樓怠硼,卻偏偏與公主長(zhǎng)得像鬼贱,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子香璃,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,969評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容