hive基础操作

第一章 Hive的基本概念

1.1 什么是Hive

​ Hive:由Facebook开源用于解决海量结构化日志的数据统计

​ Hive是基于Hadoop的一个数据仓库工具,可以将结构化的数据文件映射为一张表,并提供类SQL查询功能

本质:将HQL转换为MapReduce程序

  1. Hive处理的数据存储在HDFS上
  2. HIve分析数据底层的默认实现是MapReduce
  3. 执行程序运行在Yarn上

1.2 Hive的由优缺点

1.2.1 优点
  1. 操作接口采用类SQL语法提供快速方法的能力
  2. 避免去写MapReduce,减少开发人员的学习成本
  3. Hive的执行延迟比较高,因此Hive常用于数据分析,对实时性要求不高的场所
  4. Hive的优势在于大数据,对于处理小数据没有优势,因此Hive的执行延迟比较高
  5. Hive支持用户自定义函数,用户可以根据自己的需求来实现自己的函数
1.2.2 缺点
  • Hive的HQL表达能力有限

    1. 迭代算法无法表达
    2. 数据挖掘方法不擅长
  • Hive的效率比较低

    1. Hive自动生成的MapReduce作业,通常情况乱下不够智能化
    2. Hive调优比较困难,粒度较粗

第二章 Hive操作

2.1 Hive 常用交互命令

[root@slave01 ~]# hive --help
Usage ./hive <parameters> --service serviceName <service parameters>
Service List: beeline cli help hiveburninclient hiveserver2 hiveserver hwi jar lineage metastore metatool orcfiledump rcfilecat schemaTool version 
Parameters parsed:
  --auxpath : Auxillary jars 
  --config : Hive configuration directory
  --service : Starts specific service/component. cli is default
Parameters used:
  HADOOP_HOME or HADOOP_PREFIX : Hadoop install directory
  HIVE_OPT : Hive options
For help on a particular service:
  ./hive --service serviceName --help
Debug help:  ./hive --debug --help

  • "-e"不进入hive的交互窗口执行sql语句
[root@slave01 ~]# hive -e "show databases;"

Logging initialized using configuration in jar:file:/opt/Hive1.1/apache-hive-1.1.0-bin/lib/hive-common-1.1.0.jar!/hive-log4j.properties
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/opt/Hadoop2.6/hadoop-2.6.0/share/hadoop/common/lib/slf4j-log4j12-1.7.5.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/opt/Hive1.1/apache-hive-1.1.0-bin/lib/hive-jdbc-1.1.0-standalone.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [org.slf4j.impl.Log4jLoggerFactory]
OK
default
Time taken: 0.603 seconds, Fetched: 1 row(s)

  • -f 通过执行脚本的方式执行hql语句
[root@slave01 ~]# cat hive.sql 
show databases;
[root@slave01 ~]# hive -f hive.sql 

Logging initialized using configuration in jar:file:/opt/Hive1.1/apache-hive-1.1.0-bin/lib/hive-common-1.1.0.jar!/hive-log4j.properties
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/opt/Hadoop2.6/hadoop-2.6.0/share/hadoop/common/lib/slf4j-log4j12-1.7.5.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/opt/Hive1.1/apache-hive-1.1.0-bin/lib/hive-jdbc-1.1.0-standalone.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [org.slf4j.impl.Log4jLoggerFactory]
OK
default
Time taken: 0.542 seconds, Fetched: 1 row(s)

2.2 Hive其他命令操作

  1. 在hive cli命令窗口如何查看hdfs文件系统

    hive (default)> dfs -ls /;
    Found 10 items
    drwxrwxrwx   - root supergroup          0 2019-10-08 08:13 /file3_1
    drwxrwxrwx   - root supergroup          0 2019-10-08 14:27 /hbase
    
  2. 在Hive cli命令窗口如何查看本地文件系统

    hive (default)> ! ls /opt;
    Hadoop2.6
    Hbase1.2
    Hive1.1
    
  3. 查看hive中输入的的所有历史命令

    1. 进入到当前用户的根目录/root或/home/>>>

    2. 查看.hivehistory文件

      [root@slave01 ~]# cat  .hivehistory 
      

第三章 Hive的数据类型

3.1 基本数据类型

Hive数据类型java 数据类型长度例子
tinyintbyte1byte有符号整数20
smaliintshort2byte有符号整数20
Intint4byte有符号整数20
bigIntlong8byte有符号整数20
booleanboolean布尔类型,true或者falseTrue,false
floatfloat单精度浮点数3.14159
doubledouble双精度浮点数3.14159
Stringstring字符串系列“hello word"
timestamp时间类型
binany字节数据

对于Hive的string类型相当于数据库的Varchar类型,该类型是一个可变的字符串,不过他不能声明其中最多能存储多少个字符,理论上2GB

3.2 集合数据类型

数据类型描述语法示例
STRUCT和c语言中的struct类似,都可以通过”点“符号访问元素内容,如果某个列的数据类型是struct(first string,last string),那么第一个元素可以通过字段.first来引用struct()
MapMap是一组建-值对元组集合,使用数组表示法可以访问数据。例如,如果某个列的数数据类型是Map,其中键->值对是”first"->“join"和”last"->“doe”,那么可以通过字段名[‘last’]获取最后一个元素map()
ARRAy()数组是组具有相同类型和名称的变量的集合,这些变量称为数组的元素,每个数组元素都有一个编号,编号从0开始Array()

Hive有三种复杂数据类型ARRAY、Map、和STRUCT。Array和Map与Java中的Array和map类似,而STRUCT与c语言中的Struct类似,他封装了一个命名字段集合

实例:

/*数据格式:
{
	"name":"songsong",
	"friends":["binging,"lisi"],
	"children:{
		"xiaotian":18,
		"susu":19
	}
	"address":{
		"street":"hui long guan",
		"city":"beijing"
	}
}
// 基于上述数据结构,我们在Hive中创键对应的表,并导入数据
hive (default)> create database test;
OK
Time taken: 0.633 seconds
hive (default)> show databases;
OK
default
test
Time taken: 0.104 seconds, Fetched: 2 row(s)
hive (default)> create table test.Onetest (
              > name string,
              > friends array<string>,
              > children map<string,int>, 
              > address struct<street:string,city:string>)
              > row format delimited fields terminated by ',' --列分隔符
              > collection items terminated by '_' -- Map struct 和array的分隔符(数据分隔符)
              > map keys terminated by ':' --Map中的key与Value的分隔符
              > lines terminated by '\n'; 
OK
Time taken: 0.32 seconds
//创键数据文件hive.json
[root@slave01 ~]# cat Hive.json 
songsong,bingbing_lili,xiao songlong guan_beijing
sgsong,bingbing_lili,xiao song:1ng guan_beijing
ongsong,bingbing_lili,xiao song:ong guan_beijing

//导入文件数据到测试表
hive (default)> use test;
OK
Time taken: 0.012 seconds
hive (test)> load data local inpath "/root/Hive.json" into table Onetest;
Loading data to table test.onetest
Table test.onetest stats: [numFiles=1, totalSize=162]
OK
Time taken: 1.162 seconds
//查看数据
[root@slave01 ~]# hive -e "select * from test.onetest;"

Logging initialized using configuration in jar:file:/opt/Hive1.1/apache-hive-1.1.0-bin/lib/hive-common-1.1.0.jar!/hive-log4j.properties
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/opt/Hadoop2.6/hadoop-2.6.0/share/hadoop/common/lib/slf4j-log4j12-1.7.5.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/opt/Hive1.1/apache-hive-1.1.0-bin/lib/hive-jdbc-1.1.0-standalone.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [org.slf4j.impl.Log4jLoggerFactory]
OK
songsong	["bingbing","lili"]	{"xiao song":18,"xiaoxiao song":19}	{"street":"hui long guan","city":"beijing"}
sgsong	["bingbing","lili"]	{"xiao song":18,"xiaoxiao song":19}	{"street":"hui long guan","city":"beijing"}
ongsong	["bingbing","lili"]	{"xiao song":18,"xiaoxiao song":19}	{"street":"hui long guan","city":"beijing"}

  • 查看某个字段的数据
hive> select friends from test.onetest;
OK
["bingbing","lili"]
["bingbing","lili"]
["bingbing","lili"]
  • 访问数组的内容
    hive (test)> select friends[0] from onetest;
    OK
    bingbing
    bingbing
    bingbing
    Time taken: 0.247 seconds, Fetched: 7 row(s)
    hive (test)> select friends[1] from onetest;
    OK
    lili
    lili
    lili
    
  • Map的访问
    hive (test)> select children from onetest;
    OK
    {"xiao song":18,"xiaoxiao song":19}
    {"xiao song":18,"xiaoxiao song":19}
    {"xiao song":18,"xiaoxiao song":19}
    hive (test)> select children["xiao song"] from onetest;
    OK
    18
    18
    18
    
    
  • struct的访问
    hive (test)> select addresses.street from onetest;
    OK
    hui long guan
    hui long guan
    hui long guan
    

3.3 Hive数据类型转换

Hive的原子数据类型可以进行隐式转换的,类似于Java的类型转换,例如某表达式使用INT类型,tinyint会自动转换为Int类型,但是Hive不会经行反向转换,例如某表达式使用tinyint类型,int不会自动转换tinyint类型,它会返回错误,除非使用cast操作

1. 隐式类型转换规则如下
  1. 任何整数类型都可以隐式地转换为一个范围更广的类型,如tinyint可以转换int,int可以转换bigint
  2. 所有整数类型,float和string类型都可以隐式地转换成double类型
  3. tinyint,smailint、int都可以转换为float
  4. boolean 类型不可以转换为任何其他的数据类型
2. 可以使用cast操作显示进行数据类型转换

例如casst(“1” as int) 将字符串"1"转换成整数1,如果强制类型转换失败,如执行

cast("X"as int) ,表达式返回空值Null

3.对cast有一下几点需要说明的:

(1)、如果将浮点型的数据转换成int类型的,内部操作是通过round()或者floor()函数来实现的,而不是通过cast实现!

(2)、对于BINARY类型的数据,只能将BINARY类型的数据转换成STRING类型。如果你确信BINARY类型数据是一个数字类型(a number),这时候你可以利用嵌套的cast操作,比如a是一个BINARY,且它是一个数字类型,那么你可以用下面的查询:

SELECT (cast(cast(a as string) asdouble)) from src;

我们也可以将一个String类型的数据转换成BINARY类型。

(3)、对于Date类型的数据,只能在Date、Timestamp以及String之间进行转换。下表将进行详细的说明:

第四章 DDL数据定义

4.1 create 创键

4.1.1 创键数据库
create database [if not exists] database_name location 'dataresource_path'
comment "描述信息"
参数说明:
	if not exists:避免创键同名数据库而抛出错误
	location:修改数据库源文件默认位置
	comment:为这个数据库增加描述信息
  1. 其他操作说明

    1.使用某个数据库
    	use database_name;
    2. 显示当前数据库下的所有表
    	show tables;
    3. 显示当前使用数据
    	set hive.cli.print.current.db=true
    3. 删除数据库 (if exists 避免数据库不存在而抛出错误)
    	drop database  if exists databases_name
    
4.1.2 创键表
create [external] table [if not exists] table_name
[(col_name data_type [comment col_comment],...)]
[comment table_comment]
[partitioned by (col_name dta_type[comment col_comment],...)]
[clustered by (col_name,col_name,...)]
[sorted by (col_name[Asc|desc],...)] into num_buckets buckets]

字段解释说明:

create table: 创键一个指定名称的表,
if not exists:避免创键同名数据表而抛出错误
external: 关键字可以让用户创键一个外部表,在建表的同时指定一个指向实际数据的路径(path),Hive创键内部		表时,会将数据移动到数据仓库指向的路径;若创建外部表,仅记录数据所在的路径,不对数据的位置做任何			改变,在删除表的时候,内部表的元数据会被一起删除,而外部只删除元数据的路径,不删除源数据
comment:为表和字段添加注释说明
partitioned by :创键分区表
clustered by :创键分桶表
sorted by :不常用

row format delimited [fields terminted by char] [collection items terminated by char] [map keys terminated by char] [lines terminated by char] | sered serde_name[with serdeproperties(property_name=property_value,property_name=property_value,...)]
参数说明:
    用户在建表的时候可以自定义serde或者使用自带的serde。如果没有指定row format 或者row format delimited ,将会使用自带的serde,在建表的时候,用户还需要为表指定列,用户在指定表的列的同时也会将自定义的serde,Hive通过serde确定表的具体的列的数据
Serde 是Serialize/Deserilize的简称,目的是用于序列化和反序列化
stored as:指定存储文件类型,Hive本身支持的文件格式只有:Text File,Sequence File。如果文件数据是纯文本,可以使用 [STORED AS TEXTFILE]。如果数据需要压缩,使用 [STORED AS SEQUENCE] 
location:指定表在hdfs上的存储位置
like:允许用户复制现在的表结构,但不复制数据
fields terminated by "分隔符":指定hdfs每个字段的分割符
lines terminated by "分割符":指定hdfs行数据行分割符,默认”/n"
collection items terminated by cahr:指定Map、Struct、Array的分隔符
map keys terminated by char:指定ma和key之间的分隔符

4.2 select 查询

4.2.1 基本查询
1. 显示数据库详细信息
	desc database db_name;
2. 切换数据库
	use db_naem;
3. 显示所有数据库
	show databases;
4. 显示当前数据库的所有表
	show tables;
5. 指定数据库,显示所有表
	show tables in db_name;
6.查看表的详细信息 (fromatted 代替entend可以提供更加可读的和冗长的传输信息)
	describe extended db_name.tb_name;

4.3 Alter 修改

4.3.1 修改数据库
  1. 用户可以使用alter database 命令为某个数据库的dbproperties设置键-值对属性值,来描述这个数据库的属性信息,数据库的其他元数据信息都是不可变的

    alter database database_name set dbproperties ('edited-by'='joe dba')
    
4.3.2 修改表
  1. 修改字段的数据类型

    Alter table tb_name  change column old_clo_name  new_clo_name  data_typer
    
  2. 表重命名

    alter tb tb_name rename to new_db_name.5
    
  3. 修改列信息

    alter table tb_name change column old_column_name new_column_name data_type comment after column_name;
    	参数说明:
    		column:字段名
    		data_typ:数据类型
    		comment:注释说明
    		after column_name:指定某个字段的后面,可用first将该字段移动到第一个位置
    
  4. 增加列

    alter table tb_name add columns(column_name1 type,.....)
    

4.4 drop 删除

4.4.1 删除数据库
drop db if exists db_name cascade;
参数说明:
	if exists:避免数据库不存在而报错
	cascade:数据库不为空则需要使用该参数。进行强制删除	
4.4.2 删除数据表
drop tb if exists db_name;
参数说明:
	if exists:避免数据表不存在而报错
4.4.3 删除内表的数据
删除内部表中数据(保留表结构)

truncate table 表名; 

4.5 hive数据导入导出

4.5.1 数据导入
语法:
	load data [local] inpath  “filepath"  [overwrite] into table tablename [partition (partcol1=val1,partcol2=val2 ...)]
	tblproperties("skip.header.line.count"="1");
参数说明:
	local:指的是本地操作系统的文件路径,否则默认为HDFS的文件路径;
	tblproperties("skip.header.line.count"="1"):忽略首行;
	overwrite:覆盖
1. 单个查询语句中创键表并加载数据	
	create table  table_name sql 语句
2. 通过查询语句向表中插入数据
	先建表
    insert [overwrite|into] table table_name [parttion(partcol1=val1....)] sql语句
    overwrite:覆盖
    into:追加
4.5.2 数据导出
1. 直接**cp** 源文件
   hdfs dfs -cp source_path target_path
2. 使用insert...directory
   insert overwrite local directory "local_path" sql语句
   local:设置位本地路径,如果不设置默认为Hdfs文件地址

4. 6分区表

分区表实际上就是对应一个HDFS文件系统上的独立的文件夹,该文件夹下是该分区所有的数据文件,Hive中的分区就是分目录,把一个大的数据集根据业务需求分割成小的数据集,在查询时通过where子句中的表达式选择查询所需要的指定的分区,这样的查询效率会提高很多

第五章 Hive函数

5.1 系统内置函数

  1. 查看系统自带的函数

    hive> show functions;
    
  2. 显示自带函数的用法

    hive> desc function =;
    OK
    a = b - Returns TRUE if a equals b and false otherwise
    Time taken: 0.047 seconds, Fetched: 1 row(s)
    
    
  3. 详细显示自带的函数用法

    hive> desc function extended max;
    OK
    max(expr) - Returns the maximum value of expr
    Time taken: 0.385 seconds, Fetched: 1 row(s)
    

5.2 自定义函数

  1. UDF(User-Defind-Function)一进一出
  2. UDAF(User-Defind Aggregation Function)聚合函数,多进一出
  3. UDTF(User-Defind Table_Generating Function)一进多出
  • 编程步骤

    1. 继承org.apache.hadoop.hive.UDF

    2. 需要实现evaluate函数;evaluate函数支持重载

    3. 在hive的命令行窗口创键函数

      • ​ 添加jar

        add jar linux_jar_path
        
      • 创键function

        create [temporary] function [dbname.]function_name AS class_name;
        
    4. 在hive的命令行窗口删除函数

      Drop [temporary] function [if exists] [dbname.]function_name;
      

第六章 HQL查询

6.1 SELECT…FROM

6.1.1 使用正则表达式来指定列
SELECT COL1* from table_name
6.1.2 使用列值进行计算
SELECT SUM(COL_NAME) FROM TB_NAME;
6.1.3 算术运算符
运算符类型描述
A + B数值A 加 B
A - B数值A 减 B
A * B数值A 乘 B
A / B数值A 除以 B,返回商
A % B数值A 除以B的余数
A & B数值
A | B数值
A ^ B数值异或
~A数值取反
6.1.4 使用函数
  1. 数学函数,用于处理单个列的(常用)

    返回值类型样式描述
    BIGINTround(DOUBLE D)返回Double型d的bigint类型的近似值
    BOUBLEround(DOUBLE d,INT n)返回Double型d的保留n位小数的double近似值
    BIGINTfloor(DOUBLE d)d是DOUBLE类型的,返回<=d的最大BIGINT型值
    BIGINTceil(DOUBLE d) ceiling(DOUBLE d)d是DOUBLE类型,返回>=d的最小BIGINT型值
    DOUBLErand() rand(INT seed)每行返回一个DOUBLE型随机数,整数seed是随机因子
    DUOBLEexp(DOUBLE d)返回e的d幂次方,返回的是个DOUBLE型值
    DOUBLEsqrt(DOUBLE d)计算d的平方根
    DOUBLEabs(DOUBLE d)计算Double 型的d的绝对值
    DOUBLEpi()数学常数pi,也就是圆周率
  2. 聚合函数 对多行进行计算,然后得到一个结果值,即用户自定义函数

    返回值类型样式描述
    BIGINTcount(*)计算总行数,包括null值的行
    BIFGINTcount(expr)计算提供的expr表达式的值非null的行数
    BIGINTcount(DISTINCT expr[,expr_.])计算提供的expr表达式的值排重后的非null的行数
    DOUBLEsum(col)计算指定行的值的和
    DOUBLEsum(DISTINCT col)计算排重后值的和
    DOUBLEavg(col)计算指定行的值的平均值
    DOUBLEavg(DISTINCT col)计算排重后值的平均值
    DOUBLEmin(col)计算指定行的最小值
    DOUBLEmax(col)计算指定行的最大值
    DOUBLEvariance(col),var_pop(col)返回集合col中的一组数值的方差
    DOUBLEvar_samp(col)返回集合col中的一组数值的样本方差
    DOUBLEstddev_pop(col)返回一组数值的标准偏差(标准差)
    DOUBLEstddev_samp(col0返回一组数值的样本标准偏差
    DOUBLEcovar_pop(col1,col2)返回一组数值的协方差
    DOUBLEcovar_samp(col1.col2)返回一组数值的样本协方差
    DOUBLEcorr(col1,col2)返回两组数值的相关系数
    DOUBLEpercentile(BIGINT int_expr,p)int_expr在P([o,1]处所对应的百分比),p是一个Double型数值
    ARRAYpercentile(BIGINT int_expr,Array(p1[,p2]…))int_expr在P([o,1]处所对应的百分比),p是一个Double型数组
    DOUBLEpercentile_approx(DOUBLE col ,p[,NB] )col 在P([o,1]处所对应的百分比),p是一个Double型数值,NB是用于估计的直方图中的仓库数量(默认1000)
    STRINGupper(STRING A) ucase(STRING A)将字符串中的字母转换成大写字母
    STRINGfrom_unixtime(BIGINT unixtime[,String fromat])将时间戳秒数转换成UTC时间,并用字符串表示,可以通过format规定的时间格式,指定输出的时间格式
    BIGINTunix_timestamp()获取当前本地时区下的当前时间戳
    BIGINTunix_timestamp(String date)输入的时间字符串格式必须是yyyy-MM-dd HH:mm:ss 如果不符合则返回0,如果符合则返回Unix的时间戳
    BIGINTunix_timestamp(STRING date,STRING pattern)将指定时间字符串格式字符串转换成Unix时间戳,如果格式不对则返回0
    STRINGto_date(STRING timestamp)返回时间字符串的日期部分
    INTyear(STRING data返回时间字符串的年份并使用int类型
    INTdatadiff(STRING enddate,STRING startdate)计算开始时间到结束时间相差的天数
    STRINGdate_add(STRING startdate,INt days)为开始时间增加N天
    STRINGdate_sub(STRING startdate,INt days)为开始时间减少天
6.1.5 LIMIT语句
查询返回指定行数
select * from tb_name limit n
6.1.6 case … when…then
例子:
	select name,salary,
		case 
			when salary < 5 then 1
			when salary >=5 and salary < 8 then 2
			else 3
		and as ab
	from tb_name

6.2 WHERE 语句

SELECT 语句用于选取字段,WHERE语句用于过滤条件

6.2.1 谓词操作符
操作符支持数据类型描述
a = b基本数据类型如果a等于b则返回true,否则就返回false
a<=>b基本数据类型如果a和b都为null,则返回True,其他的和等号(=)操作符的结果一致,如果任意为null,则结果为null
a<>b,a!=b基本数据类型a或b为null 则返回null ;如果a不等于b则返回true,反之则为false,
6.2.2 LIKE 和RLIKE

rlike后面的字符串表达式含义:

​ (.):表示和任意的字符匹配

​ (*):表示重复左边的字符串

​ 9|):或

6.3 GROUP BY语句

group by 语句:通常会和聚合函数一起使用,按照一个或者多个列对结果进行分组,然后对每个组执行操作

6.3.1 HAVING 语句

having 子句允许用户通过一个简单的语法完成原本需要通过子查询才能对group by语句产生的分组进行条件过滤的任务

6.4 Join语句

6.4.1 INNER JOIN内连接

内连接中(INNER JOIN)中,只有进行连接的两个表中都存在与连接标准相匹配的数数据才会保留下来

例:
	select tb1.col1,tb1.col2,tb2.col3 
	from tb1 join tb2 on tb1.col1 = tb2.col2p
6.4.2 LEFT OUTER JOIN

左外连接通过关键字LEFT OUTER 进行标识

6.4.3 OUTER JOIN

外连接

6.4.4 RIGHT OUTER JOIN

右外连接

6.4.5 full OUTER JOIN

完全外连接

6.5 排序

sort by ,其只会在每个reducer中对数据进行排序,执行一个局部排序过程
order by ,对查询结果集做一个全局排序
默认asc 升序
desc 降序

6.7 类型转换

select col1,col2 from tb where cast(col1 type) < ?

6.8 UNION ALL

unionall 可以将2个或多个表进行合并,每一个union 子查询都必须具有相同的列,而且对应的每个字段类型都是一样的

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值