Hive-壓縮和存儲

1.1 Hadoop源碼編譯支持Snappy壓縮

1.1.1 資源準備
1.CentOS聯(lián)網(wǎng)

配置CentOS能連接外網(wǎng)。Linux虛擬機ping www.baidu.com是暢通的

注意:采用root角色編譯句喷,減少文件夾權限出現(xiàn)問題

2.jar包準備(hadoop源碼镣典、JDK8 、maven唾琼、protobuf)

(1)hadoop-2.8.4-src.tar.gz

(2)jdk-8u144-linux-x64.tar.gz

(3)snappy-1.1.3.tar.gz

(4)apache-maven-3.0.5-bin.tar.gz

(5)protobuf-2.5.0.tar.gz

1.1.2 jar包安裝
0.注意:

所有操作必須在root用戶下完成

1.JDK解壓兄春、配置環(huán)境變量JAVA_HOME和PATH,驗證java-version(如下都需要驗證是否配置成功)

解壓:

tar -zxf jdk-8u144-linux-x64.tar.gz -C /opt/module/

修改環(huán)境變量

vi /etc/profile

修改內容:

#JAVA_HOME
export JAVA_HOME=/opt/module/jdk1.8.0_144
export PATH=$PATH:$JAVA_HOME/bin

使環(huán)境變量生效

source /etc/profile

驗證命令:java -version

2.Maven解壓锡溯、配置 MAVEN_HOME和PATH赶舆。

解壓

tar -zxvf apache-maven-3.0.5-bin.tar.gz -C /opt/module/

修改環(huán)境變量

vi /etc/profile

修改內容

#MAVEN_HOME
export MAVEN_HOME=/opt/module/apache-maven-3.0.5
export PATH=$PATH:$MAVEN_HOME/bin

使環(huán)境變量生效

source /etc/profile

驗證命令:mvn -version

1.1.3 編譯源碼
1.準備編譯環(huán)境
[root@bigdata111 software]# yum install svn

[root@bigdata111 software]# yum install autoconf automake libtool cmake

[root@bigdata111 software]# yum install ncurses-devel

[root@bigdata111 software]# yum install openssl-devel

[root@bigdata111 software]# yum install gcc*
2.編譯安裝snappy
[root@bigdata111 software]# tar -zxvf snappy-1.1.3.tar.gz -C /opt/module/

[root@bigdata111 module]# cd snappy-1.1.3/

[root@bigdata111 snappy-1.1.3]# ./configure

[root@bigdata111 snappy-1.1.3]# make

[root@bigdata111 snappy-1.1.3]# make install

查看snappy庫文件

[root@bigdata111 snappy-1.1.3]# ls -lh /usr/local/lib |grep snappy
3.編譯安裝protobuf
[root@bigdata111 software]# tar -zxvf protobuf-2.5.0.tar.gz -C /opt/module/

[root@bigdata111 module]# cd protobuf-2.5.0/

[root@bigdata111 protobuf-2.5.0]# ./configure 

[root@bigdata111 protobuf-2.5.0]#  make 

[root@bigdata111 protobuf-2.5.0]#  make install

查看protobuf版本以測試是否安裝成功

[root@bigdata111 protobuf-2.5.0]# protoc --version
4.編譯hadoop native
[root@bigdata111 software]# tar -zxvf hadoop-2.8.4-src.tar.gz

[root@bigdata111 software]# cd hadoop-2.8.4-src/

[root@bigdata111 software]# mvn clean package -DskipTests -Pdist,native -Dtar -Dsnappy.lib=/usr/local/lib -Dbundle.snappy

????執(zhí)行成功后,/opt/software/hadoop-2.8.4-src/hadoop-dist/target/hadoop-2.8.4.tar.gz即為新生成的支持snappy壓縮的二進制安裝包祭饭。

1.2 Hadoop壓縮配置

1.2.1 MR支持的壓縮編碼
壓縮格式 工具 算法 文件擴展名 是否可切分
DEFAULT DEFAULT .deflate
Gzip gzip DEFAULT .gz
bzip2 bzip2 bzip2 .bz2
LZO lzop LZO .lzo
Snappy Snappy .snappy

????為了支持多種壓縮/解壓縮算法芜茵,Hadoop引入了編碼/解碼器,如下表所示

壓縮格式 對應的編碼/解碼器
DEFLATE org.apache.hadoop.io.compress.DefaultCodec
gzip org.apache.hadoop.io.compress.GzipCodec
bzip2 org.apache.hadoop.io.compress.BZip2Codec
LZO com.hadoop.compression.lzo.LzopCodec
Snappy org.apache.hadoop.io.compress.SnappyCodec

壓縮性能的比較

壓縮算法 原始文件大小 壓縮文件大小 壓縮速度 解壓速度
gzip 8.3GB 1.8GB 17.5MB/s 58MB/s
bzip2 8.3GB 1.1GB 2.4MB/s 9.5MB/s
LZO 8.3GB 2.9GB 49.3MB/s 74.6MB/s

On a single core of a Core i7 processor in 64-bit mode, Snappy compresses at about 250 MB/sec or more and decompresses at about 500 MB/sec or more.

1.2.2 壓縮參數(shù)配置

要在Hadoop中啟用壓縮倡蝙,可以配置如下參數(shù)(mapred-site.xml文件中):

參數(shù) 默認值 階段 建議
io.compression.codecs(在core-site.xml中配置) org.apache.hadoop.io.compress.DefaultCodec
org.apache.hadoop.io.compress.GzipCodec
org.apache.hadoop.io.compress.BZip2Codec
org.apache.hadoop.io.compress.Lz4Codec
輸入壓縮 Hadoop使用文件擴展名判斷是否支持某種編解碼器
mapreduce.map.output.compress false mapper輸出 這個參數(shù)設為true啟用壓縮
mapreduce.map.output.compress.codec org.apache.hadoop.io.compress.DefaultCodec mapper輸出 使用LZO九串、LZ4或snappy編解碼器在此階段壓縮數(shù)據(jù)
mapreduce.output.fileoutputformat.compress false reducer輸出 這個參數(shù)設為true啟用壓縮
mapreduce.output.fileoutputformat.compress.codec org.apache.hadoop.io.compress. DefaultCodec reducer輸出 使用標準工具或者編解碼器,如gzip和bzip2
mapreduce.output.fileoutputformat.compress.type RECORD reducer輸出 SequenceFile輸出使用的壓縮類型:NONE和BLOCK

1.3 開啟Map輸出階段壓縮

????開啟map輸出階段壓縮可以減少job中map和Reduce task間數(shù)據(jù)傳輸量寺鸥。具體配置如下:

案例實操:
(1)開啟hive中間傳輸數(shù)據(jù)壓縮功能,默認為false

hive (default)>set hive.exec.compress.intermediate=true;

(2)開啟mapreduce中map輸出壓縮功能,默認為false

hive (default)>set mapreduce.map.output.compress=true;

(3)設置mapreduce中map輸出數(shù)據(jù)的壓縮方式

hive (default)>set mapreduce.map.output.compress.codec= org.apache.hadoop.io.compress.SnappyCodec;

(4)執(zhí)行查詢語句

hive (default)> select count(ename) name from emp;

1.4 開啟Reduce輸出階段壓縮

????當Hive將輸出寫入到表中時猪钮,輸出內容同樣可以進行壓縮。屬性hive.exec.compress.output控制著這個功能胆建。用戶可能需要保持默認設置文件中的默認值false烤低,這樣默認的輸出就是非壓縮的純文本文件了。用戶可以通過在查詢語句或執(zhí)行腳本中設置這個值為true眼坏,來開啟輸出結果壓縮功能拂玻。

案例實操:
(1)

hive (default)> set mapreduce.job.reduces=3;

(2)開啟hive最終輸出數(shù)據(jù)壓縮功能,默認為false

hive (default)>set hive.exec.compress.output=true;

(3)開啟mapreduce最終輸出數(shù)據(jù)壓縮,默認為false

hive (default)>set mapreduce.output.fileoutputformat.compress=true;

(4)設置mapreduce最終數(shù)據(jù)輸出壓縮方式

hive (default)> set mapreduce.output.fileoutputformat.compress.codec = org.apache.hadoop.io.compress.SnappyCodec;

(5)設置mapreduce最終數(shù)據(jù)輸出壓縮為塊壓縮

hive (default)> set mapreduce.output.fileoutputformat.compress.type=BLOCK;

(6)測試一下輸出結果是否是壓縮文件

hive (default)> insert overwrite local directory '/opt/module/datas/distribute-result' select * from emp distribute by deptno sort by empno desc;

測試:不設置reduce酸些,結果是否是壓縮格式

hive (default)> set mapreduce.job.reduces=-1;

insert overwrite local directory '/opt/module/datas/distribute-result' select * from test;

1.5 文件存儲格式

Hive支持的存儲數(shù)的格式主要有:TEXTFILE 、SEQUENCEFILE檐蚜、ORC魄懂、PARQUET。

簡寫:

  • 行儲存:textFile 闯第、 sequencefile 市栗、
  • 列儲存:orc 、parquet
1.5.1 列式存儲和行式存儲

上圖左邊為邏輯表咳短,右邊第一個為行式存儲填帽,第二個為列式存儲。

1.行存儲的特點:

????查詢滿足條件的一整行數(shù)據(jù)的時候咙好,列存儲則需要去每個聚集的字段找到對應的每個列的值篡腌,行存儲只需要找到其中一個值,其余的值都在相鄰地方勾效,所以此時行存儲查詢的速度更快嘹悼。

2.列存儲的特點:

????因為每個字段的數(shù)據(jù)聚集存儲,在查詢只需要少數(shù)幾個字段的時候层宫,能大大減少讀取的數(shù)據(jù)量杨伙;每個字段的數(shù)據(jù)類型一定是相同的,列式存儲可以針對性的設計更好的設計壓縮算法萌腿。

????TEXTFILE和SEQUENCEFILE的存儲格式都是基于行存儲的限匣;
????ORC和PARQUET是基于列式存儲的

1.5.2 TextFile格式

????默認格式,數(shù)據(jù)不做壓縮毁菱,磁盤開銷大米死,數(shù)據(jù)解析開銷大《Ψ可結合Gzip哲身、Bzip2使用,但使用Gzip這種方式贸伐,hive不會對數(shù)據(jù)進行切分勘天,從而無法對數(shù)據(jù)進行并行操作。

1.5.3 Orc格式

????Orc (Optimized Row Columnar)是Hive 0.11版里引入的新的存儲格式捉邢。

????可以看到每個Orc文件由1個或多個stripe組成脯丝,每個stripe250MB大小,這個Stripe實際相當于RowGroup概念伏伐,不過大小由4MB->250MB宠进,這樣應該能提升順序讀的吞吐率。每個Stripe里有三部分組成藐翎,分別是Index Data材蹬,Row Data实幕,Stripe Footer:

(1)Index Data:一個輕量級的index,默認是每隔1W行做一個索引堤器。這里做的索引應該只是記錄某行的各字段在Row Data中的offset昆庇。

(2)Row Data:存的是具體的數(shù)據(jù),先取部分行闸溃,然后對這些行按列進行存儲整吆。對每個列進行了編碼,分成多個Stream來存儲辉川。

(3)Stripe Footer:存的是各個Stream的類型表蝙,長度等信息。

????每個文件有一個File Footer乓旗,這里面存的是每個Stripe的行數(shù)府蛇,每個Column的數(shù)據(jù)類型信息等;每個文件的尾部是一個PostScript寸齐,這里面記錄了整個文件的壓縮類型以及FileFooter的長度信息等欲诺。在讀取文件時,會seek到文件尾部讀PostScript渺鹦,從里面解析到File Footer長度,再讀FileFooter蛹含,從里面解析到各個Stripe信息毅厚,再讀各個Stripe,即從后往前讀浦箱。

1.5.4 Parquet格式

????Parquet是面向分析型業(yè)務的列式存儲格式吸耿,由Twitter和Cloudera合作開發(fā),2015年5月從Apache的孵化器里畢業(yè)成為Apache頂級項目酷窥。

????Parquet文件是以二進制方式存儲的咽安,所以是不可以直接讀取的,文件中包括該文件的數(shù)據(jù)和元數(shù)據(jù)蓬推,因此Parquet格式文件是自解析的妆棒。

????通常情況下,在存儲Parquet數(shù)據(jù)的時候會按照Block大小設置行組的大小沸伏,由于一般情況下每一個Mapper任務處理數(shù)據(jù)的最小單位是一個Block糕珊,這樣可以把每一個行組由一個Mapper任務處理,增大任務執(zhí)行并行度毅糟。Parquet文件的格式如下圖所示红选。

????上圖展示了一個Parquet文件的內容,一個文件中可以存儲多個行組姆另,文件的首位都是該文件的Magic Code喇肋,用于校驗它是否是一個Parquet文件坟乾,F(xiàn)ooter length記錄了文件元數(shù)據(jù)的大小,通過該值和文件長度可以計算出元數(shù)據(jù)的偏移量蝶防,文件的元數(shù)據(jù)中包括每一個行組的元數(shù)據(jù)信息和該文件存儲數(shù)據(jù)的Schema信息糊渊。除了文件中每一個行組的元數(shù)據(jù),每一頁的開始都會存儲該頁的元數(shù)據(jù)慧脱,在Parquet中渺绒,有三種類型的頁:數(shù)據(jù)頁、字典頁和索引頁菱鸥。數(shù)據(jù)頁用于存儲當前行組中該列的值宗兼,字典頁存儲該列值的編碼字典,每一個列塊中最多包含一個字典頁氮采,索引頁用來存儲當前行組下該列的索引殷绍,目前Parquet中還不支持索引頁。

1.5.5 主流文件存儲格式對比實驗

從存儲文件的壓縮比和查詢速度兩個角度對比鹊漠。

(一)存儲文件的壓縮比測試:

0.測試數(shù)據(jù)(log.data 大小為18.1MB)
1.TextFile

(1)創(chuàng)建表主到,存儲數(shù)據(jù)格式為TEXTFILE

create table log_text (

track_time string,

url string,

session_id string,

referer string,

ip string,

end_user_id string,

city_id string

)

row format delimited fields terminated by '\t'

stored as textfile ;

(1)向表中加載數(shù)據(jù)

hive (default)> load data local inpath '/opt/module/datas/log.data' into table log_text ;

(3)查看表中數(shù)據(jù)大小

hive (default)> dfs -du -h /user/hive/warehouse/log_text;

18.1 M /user/hive/warehouse/log_text/log.data

2/ORC

(1)創(chuàng)建表,存儲數(shù)據(jù)格式為ORC

create table log_orc(

track_time string,

url string,

session_id string,

referer string,

ip string,

end_user_id string,

city_id string

)

row format delimited fields terminated by '\t'

stored as orc ;

(2)向表中加載數(shù)據(jù)

hive (default)> insert into table log_orc select * from log_text ;

(3)查看表中數(shù)據(jù)大小

hive (default)> dfs -du -h /user/hive/warehouse/log_orc/ ;

2.8 M /user/hive/warehouse/log_orc/000000_0

3.Parquet

(1)創(chuàng)建表躯概,存儲數(shù)據(jù)格式為parquet

create table log_parquet(

track_time string,

url string,

session_id string,

referer string,

ip string,

end_user_id string,

city_id string

)

row format delimited fields terminated by '\t'

stored as parquet ;  

(2)向表中加載數(shù)據(jù)

hive (default)> insert into table log_parquet select * from log_text ;

(3)查看表中數(shù)據(jù)大小

hive (default)> dfs -du -h /user/hive/warehouse/log_parquet/ ;

13.1 M /user/hive/warehouse/log_parquet/000000_0

存儲文件的壓縮比總結:

ORC > Parquet > textFile

(二)存儲文件的查詢速度測試:

1.TextFile
hive (default)> select count(*) from log_text;

_c0
100000
Time taken: 21.54 seconds, Fetched: 1 row(s)
Time taken: 21.08 seconds, Fetched: 1 row(s)

2.ORC
hive (default)> select count(*) from log_orc;

_c0
100000
Time taken: 20.867 seconds, Fetched: 1 row(s)
Time taken: 22.667 seconds, Fetched: 1 row(s)

3.Parquet
hive (default)> select count(*) from log_parquet;

_c0
100000
Time taken: 22.922 seconds, Fetched: 1 row(s)
Time taken: 21.074 seconds, Fetched: 1 row(s)

存儲文件的查詢速度總結:查詢速度相近登钥。

1.6 存儲和壓縮結合

1.6.1 修改Hadoop集群具有Snappy壓縮方式

1.查看hadoop checknative命令使用

hadoop checknative [-a|-h]  check native hadoop and compression libraries availability

2.查看hadoop支持的壓縮方式

hadoop checknative

3.將編譯好的支持Snappy壓縮的hadoop-2.8.4.tar.gz包導入到bigdata111的/opt/software中

4.解壓hadoop-2.8.4.tar.gz到當前路徑

[itstar@bigdata111software]$ tar -zxvf hadoop-2.8.4.tar.gz

5.進入到/opt/software/hadoop-2.8.4/lib/native路徑可以看到支持Snappy壓縮的動態(tài)鏈接庫

pwd

ll

6.拷貝/opt/software/hadoop-2.8.4/lib/native里面的所有內容到開發(fā)集群的/opt/module/hadoop-2.8.4/lib/native路徑上

[itstar@bigdata111native]$ cp ../native/* /opt/module/hadoop-2.8.4/lib/native/

7.分發(fā)集群 scp 到其他集群目錄

[itstar@bigdata111lib]$ scp - r ./native/ root@主機名:絕對路徑

8.再次查看hadoop支持的壓縮類型

[itstar@bigdata111hadoop-2.8.4]$ hadoop checknative

9.重新啟動hadoop集群和hive

1.6.2 測試存儲和壓縮

官網(wǎng):https://cwiki.apache.org/confluence/display/Hive/LanguageManual+ORC

ORC存儲方式的壓縮:

Key Default Notes
orc.compress ZLIB high level compression (one of NONE, ZLIB, SNAPPY)
orc.compress.size 262,144 number of bytes in each compression chunk
orc.stripe.size 67,108,864 number of bytes in each stripe
orc.row.index.stride 10,000 number of rows between index entries (must be >= 1000)
orc.create.index true whether to create row indexes
orc.bloom.filter.columns "" comma separated list of column names for which bloom filter should be created
orc.bloom.filter.fpp 0.05 false positive probability for bloom filter (must >0.0 and <1.0)
1.創(chuàng)建一個非壓縮的的ORC存儲方式

(1)建表語句

create table log_orc_none(

track_time string,

url string,

session_id string,

referer string,

ip string,

end_user_id string,

city_id string

)

row format delimited fields terminated by '\t'

stored as orc tblproperties ("orc.compress"="NONE");

(2)插入數(shù)據(jù)

hive (default)> insert into table log_orc_none select * from log_text ;

(3)查看插入后數(shù)據(jù)

hive (default)> dfs -du -h /user/hive/warehouse/log_orc_none/ ;

7.7 M /user/hive/warehouse/log_orc_none/000000_0

2.創(chuàng)建一個SNAPPY壓縮的ORC存儲方式

(1)建表語句

create table log_orc_snappy(

track_time string,

url string,

session_id string,

referer string,

ip string,

end_user_id string,

city_id string

)

row format delimited fields terminated by '\t'

stored as orc tblproperties ("orc.compress"="SNAPPY");

(2)插入數(shù)據(jù)

hive (default)> insert into table log_orc_snappy select * from log_text ;

(3)查看插入后數(shù)據(jù)

hive (default)> dfs -du -h /user/hive/warehouse/log_orc_snappy/ ;

3.8 M /user/hive/warehouse/log_orc_snappy/000000_0

3.上一節(jié)中默認創(chuàng)建的ORC存儲方式,導入數(shù)據(jù)后的大小為

2.8 M /user/hive/warehouse/log_orc/000000_0

????比Snappy壓縮的還小娶靡。原因是orc存儲文件默認采用ZLIB壓縮牧牢。比snappy壓縮的小。

4.存儲方式和壓縮總結:

????在實際的項目開發(fā)當中姿锭,hive表的數(shù)據(jù)存儲格式一般選擇:orc或parquet塔鳍。壓縮方式一般選擇snappy,lzo呻此。

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末轮纫,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子焚鲜,更是在濱河造成了極大的恐慌掌唾,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,743評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件恃泪,死亡現(xiàn)場離奇詭異郑兴,居然都是意外死亡,警方通過查閱死者的電腦和手機贝乎,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,296評論 3 385
  • 文/潘曉璐 我一進店門情连,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人览效,你說我怎么就攤上這事却舀〕婕福” “怎么了?”我有些...
    開封第一講書人閱讀 157,285評論 0 348
  • 文/不壞的土叔 我叫張陵挽拔,是天一觀的道長辆脸。 經(jīng)常有香客問我,道長螃诅,這世上最難降的妖魔是什么啡氢? 我笑而不...
    開封第一講書人閱讀 56,485評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮术裸,結果婚禮上倘是,老公的妹妹穿的比我還像新娘。我一直安慰自己袭艺,他們只是感情好搀崭,可當我...
    茶點故事閱讀 65,581評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著猾编,像睡著了一般瘤睹。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上答倡,一...
    開封第一講書人閱讀 49,821評論 1 290
  • 那天轰传,我揣著相機與錄音,去河邊找鬼苇羡。 笑死绸吸,一個胖子當著我的面吹牛,可吹牛的內容都是我干的设江。 我是一名探鬼主播,決...
    沈念sama閱讀 38,960評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼攘轩,長吁一口氣:“原來是場噩夢啊……” “哼叉存!你這毒婦竟也來了?” 一聲冷哼從身側響起度帮,我...
    開封第一講書人閱讀 37,719評論 0 266
  • 序言:老撾萬榮一對情侶失蹤歼捏,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后笨篷,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體瞳秽,經(jīng)...
    沈念sama閱讀 44,186評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,516評論 2 327
  • 正文 我和宋清朗相戀三年率翅,在試婚紗的時候發(fā)現(xiàn)自己被綠了练俐。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,650評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡冕臭,死狀恐怖腺晾,靈堂內的尸體忽然破棺而出燕锥,到底是詐尸還是另有隱情,我是刑警寧澤悯蝉,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布归形,位于F島的核電站,受9級特大地震影響鼻由,放射性物質發(fā)生泄漏暇榴。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,936評論 3 313
  • 文/蒙蒙 一蕉世、第九天 我趴在偏房一處隱蔽的房頂上張望蔼紧。 院中可真熱鬧,春花似錦讨彼、人聲如沸歉井。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,757評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽哩至。三九已至,卻和暖如春蜜自,著一層夾襖步出監(jiān)牢的瞬間菩貌,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,991評論 1 266
  • 我被黑心中介騙來泰國打工重荠, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留箭阶,地道東北人。 一個月前我還...
    沈念sama閱讀 46,370評論 2 360
  • 正文 我出身青樓戈鲁,卻偏偏與公主長得像仇参,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子婆殿,可洞房花燭夜當晚...
    茶點故事閱讀 43,527評論 2 349

推薦閱讀更多精彩內容