文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Hive为什么这么受欢迎?看完Hive架构以及应用介绍,你就明白了!

2024-12-24 18:12

关注

Hive这个框架在Hadoop的生态体系结构中占有及其重要的地位,在实际的业务当中用的也非常多,可以说Hadoop之所以这么流行在很大程度上是因为Hive的存在。那么Hive究竟是什么,为什么在Hadoop家族中占有这么重要的地位,本篇文章将围绕Hive的体系结构(架构)、Hive的操作、Hive与Hbase的区别等对Hive进行全方面的阐述。

在此之前,先给大家介绍一个业务场景,让大家感受一下为什么Hive如此的受欢迎:

业务描述:统计业务表consumer.txt中北京的客户有多少位?下面是相应的业务数据:

  1. id      city    name    sex            
  2. 0001    beijing zhangli man  
  3. 0002    guizhou lifang  woman  
  4. 0003    tianjin wangwei man  
  5. 0004    chengde wanghe  woman  
  6. 0005    beijing lidong  man  
  7. 0006    lanzhou wuting  woman  
  8. 0007    beijing guona   woman  
  9. 0008    chengde houkuo  man  

首先我先用大家所熟悉的MapReduce程序来实现这个业务分析,完整代码如下:

  1. package IT; 
  2.  
  3. import java.io.IOException; 
  4. import java.net.URI; 
  5.  
  6. import org.apache.hadoop.conf.Configuration; 
  7. import org.apache.hadoop.fs.FSDataInputStream; 
  8. import org.apache.hadoop.fs.FileSystem; 
  9. import org.apache.hadoop.fs.Path; 
  10. import org.apache.hadoop.io.IOUtils; 
  11. import org.apache.hadoop.io.LongWritable; 
  12. import org.apache.hadoop.io.Text; 
  13. import org.apache.hadoop.mapreduce.Job; 
  14. import org.apache.hadoop.mapreduce.Mapper; 
  15. import org.apache.hadoop.mapreduce.Reducer; 
  16. import org.apache.hadoop.mapreduce.lib.input.FileInputFormat; 
  17. import org.apache.hadoop.mapreduce.lib.input.TextInputFormat; 
  18. import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat; 
  19. import org.apache.hadoop.mapreduce.lib.output.TextOutputFormat; 
  20. import org.apache.hadoop.mapreduce.lib.partition.HashPartitioner; 
  21.  
  22. public class Consumer 
  23.     public static String path1 = "hdfs://192.168.80.80:9000/consumer.txt"
  24.     public static String path2 = "hdfs://192.168.80.80:9000/dir"
  25.     public static void main(String[] args) throws Exception 
  26.     { 
  27.           FileSystem fileSystem = FileSystem.get(new URI(path1) , new Configuration()); 
  28.           if(fileSystem.exists(new Path(path2))) 
  29.           { 
  30.               fileSystem.delete(new Path(path2), true); 
  31.           } 
  32.            
  33.           Job job = new Job(new Configuration(),"Consumer"); 
  34.           FileInputFormat.setInputPaths(job, new Path(path1)); 
  35.           job.setInputFormatClass(TextInputFormat.class); 
  36.           job.setMapperClass(MyMapper.class); 
  37.           job.setMapOutputKeyClass(Text.class); 
  38.           job.setMapOutputValueClass(LongWritable.class); 
  39.            
  40.           job.setNumReduceTasks(1); 
  41.           job.setPartitionerClass(HashPartitioner.class); 
  42.              
  43.           job.setReducerClass(MyReducer.class); 
  44.           job.setOutputKeyClass(Text.class); 
  45.           job.setOutputValueClass(LongWritable.class); 
  46.           job.setOutputFormatClass(TextOutputFormat.class); 
  47.           FileOutputFormat.setOutputPath(job, new Path(path2)); 
  48.           job.waitForCompletion(true); 
  49.           //查看执行结果 
  50.           FSDataInputStream fr = fileSystem.open(new Path("hdfs://hadoop80:9000/dir/part-r-00000")); 
  51.           IOUtils.copyBytes(fr, System.out, 1024, true); 
  52.      } 
  53.     public static class MyMapper extends Mapper 
  54.     {       
  55.             public static long sum = 0L; 
  56.             protected void map(LongWritable k1, Text v1,Context context) throws IOException, InterruptedException 
  57.             { 
  58.                   String[] splited = v1.toString().split("\t"); 
  59.                   if(splited[1].equals("beijing")) 
  60.                   { 
  61.                       sum++; 
  62.                   } 
  63.             } 
  64.             protected void cleanup(Context context)throws IOException, InterruptedException 
  65.             { 
  66.                   String str = "beijing"
  67.                   context.write(new Text(str),new LongWritable(sum)); 
  68.             } 
  69.     } 
  70.     public static class MyReducer extends Reducer 
  71.     { 
  72.             protected void reduce(Text k2, Iterable v2s,Context context)throws IOException, InterruptedException 
  73.             { 
  74.                   for (LongWritable v2 : v2s) 
  75.                  { 
  76.                      context.write(k2, v2); 
  77.                  } 
  78.             }    
  79.     }    

MapReduce程序代码运行结果如下: 

从运行结果可以看出:在consumer.txt业务表中,北京的客户共有三位。下面我们将用Hive来实现相同的功能,即统计业务表consumer.txt中北京的客户有多少位?

Hive操作如下: 

Hive运行结果如下:

  1. OK 
  2. beijing 3 
  3. Time taken: 19.768 seconds, Fetched: 1 row(s) 

到这里,是不是感觉Hive这个运行框架很神奇-----对于相同的业务逻辑只需要写几行Sql命令就可以获取我们所需要的结果,这也恰恰是Hive为什么这么流行的原因,Hive的优势主要体现在:

①Hive支持标准的SQL语法,免去了用户编写MapReduce程序的过程,大大减少了公司的开发成本

②Hive的出现可以让那些精通SQL技能、但是不熟悉MapReduce 、编程能力较弱与不擅长Java语言的用户能够在HDFS大规模数据集上很方便地利用SQL 语言查询、汇总、分析数据,毕竟精通SQL语言的人要比精通Java语言的多得多

③Hive是为大数据批量处理而生的,Hive的出现解决了传统的关系型数据库(MySql、Oracle)在大数据处理上的瓶颈

好了,上面通过一个简单的小业务场景说明了Hive的巨大优势,接下来将进入本篇文章的正题。

一:Hive体系结构(架构)的介绍

1、Hive的概念:

①Hive是为了简化用户编写MapReduce程序而生成的一种框架,使用MapReduce做过数据分析的人都知道,很多分析程序除业务逻辑不同外,程序流程基本一样。在这种情况下,就需要Hive这样的用户编程接口。Hive提供了一套类SQL的查询语言,称为QL,而在创造Hive框架的过程中之所以使用SQL实现Hive是因为大家对SQL语言非常的熟悉,转换成本低,可以大大普及我们Hadoop用户使用的范围,类似作用的Pig就不是通过SQL实现的。

Hive是基于Hadoop的一个开源数据仓库系统,可以将结构化的数据文件映射为一张数据库表,并提供完整的sql查询功能,Hive可以把SQL中的表、字段转换为HDFS中的目录、文件。

②Hive是建立在Hadoop之上的数据仓库基础构架、是为了减少MapReduce编写工作的批处理系统,Hive本身不存储和计算数据,它完全依赖于HDFS和MapReduce。Hive可以理解为一个客户端工具,将我们的sql操作转换为相应的MapReduce jobs,然后在Hadoop上面运行。

在开始为大家列举的consumer.txt小业务当中,从编写Sql到最后得出Beijing 3的分析结果实际上中间走的是MapReduce程序, 只不过这个MapReduce程序不用用户自己编写,而是由Hive这个客户端工具将我们的sql操作转化为了相应的MapReduce程序,下面是我们运行sql命令时显示的相关日志:

  1. hive> select city,count(*) 
  2.     > from t4     
  3.     > where city='beijing' 
  4.     > group by city; 
  5. Total MapReduce jobs = 1 
  6. Launching Job 1 out of 1 
  7. Number of reduce tasks not specified. Estimated from input data size: 1 
  8. In order to change the average load for a reducer (in bytes): 
  9.   set hive.exec.reducers.bytes.per.reducer= 
  10. In order to limit the maximum number of reducers: 
  11.   set hive.exec.reducers.max= 
  12. In order to set a constant number of reducers: 
  13.   set mapred.reduce.tasks= 
  14. Starting Job = job_1478233923484_0902, Tracking URL = http://hadoop22:8088/proxy/application_1478233923484_0902/ 
  15. Kill Command = /usr/local/hadoop/bin/hadoop job  -kill job_1478233923484_0902 
  16. Hadoop job information for Stage-1: number of mappers: 1; number of reducers: 1 
  17. 2016-11-09 11:36:36,688 Stage-1 map = 0%,  reduce = 0% 
  18. 2016-11-09 11:36:42,018 Stage-1 map = 100%,  reduce = 0%, Cumulative CPU 1.21 sec 
  19. 2016-11-09 11:36:43,062 Stage-1 map = 100%,  reduce = 0%, Cumulative CPU 1.21 sec 
  20. 2016-11-09 11:36:44,105 Stage-1 map = 100%,  reduce = 0%, Cumulative CPU 1.21 sec 
  21. 2016-11-09 11:36:45,149 Stage-1 map = 100%,  reduce = 0%, Cumulative CPU 1.21 sec 
  22. 2016-11-09 11:36:46,193 Stage-1 map = 100%,  reduce = 0%, Cumulative CPU 1.21 sec 
  23. 2016-11-09 11:36:47,237 Stage-1 map = 100%,  reduce = 0%, Cumulative CPU 1.21 sec 
  24. 2016-11-09 11:36:48,283 Stage-1 map = 100%,  reduce = 0%, Cumulative CPU 1.21 sec 
  25. 2016-11-09 11:36:49,329 Stage-1 map = 100%,  reduce = 100%, Cumulative CPU 3.7 sec 
  26. 2016-11-09 11:36:50,384 Stage-1 map = 100%,  reduce = 100%, Cumulative CPU 3.7 sec 
  27. MapReduce Total cumulative CPU time: 3 seconds 700 msec 
  28. Ended Job = job_1478233923484_0902 
  29. MapReduce Jobs Launched:  
  30. Job 0: Map: 1  Reduce: 1   Cumulative CPU: 3.7 sec   HDFS Read: 419 HDFS Write: 10 SUCCESS 
  31. Total MapReduce CPU Time Spent: 3 seconds 700 msec 
  32. OK 
  33. beijing 3 
  34. Time taken: 19.768 seconds, Fetched: 1 row(s) 

从日志可以看出,Hive将我们的sql命令解析成了相应的MapReduce任务,最后得到了我们的分析结果。

③Hive可以认为是MapReduce的一个封装、包装。Hive的意义就是在业务分析中将用户容易编写、会写的Sql语言转换为复杂难写的MapReduce程序,从而大大降低了Hadoop学习的门槛,让更多的用户可以利用Hadoop进行数据挖掘分析。

为了让大家容易理解Hive的实质-------“Hive就是一个SQL解析引擎,将SQL语句转化为相应的MapReduce程序”这句话,博主用一个图示进行示例: 

从图示可以看出,Hive从某种程度上讲就是很多“SQL—MapReduce”框架的一个封装,可以将用户编写的Sql语言解析成对应的MapReduce程序,最终通过MapReduce运算框架形成运算结果提交给Client。

2、Hive体系结构的介绍

下面是Hive的体系结构图: 

Hive的体系结构可以分为以下几个部分:

①用户接口:包括shell命令、Jdbc/Odbc和WebUi,其中最常用的是shell这个客户端方式对Hive进行相应操作

②Hive解析器(驱动Driver):Hive解析器的核心功能就是根据用户编写的Sql语法匹配出相应的MapReduce模板,形成对应的MapReduce job进行执行。

③Hive元数据库(MetaStore):Hive将表中的元数据信息存储在数据库中,如derby(自带的)、Mysql(实际工作中配置的),Hive中的元数据信息包括表的名字、表的列和分区、表的属性(是否为外部表等)、表的数据所在的目录等。Hive中的解析器在运行的时候会读取元数据库MetaStore中的相关信息。

在这里和大家说一下为什么我们在实际业务当中不用Hive自带的数据库derby,而要重新为其配置一个新的数据库Mysql,是因为derby这个数据库具有很大的局限性:derby这个数据库不允许用户打开多个客户端对其进行共享操作,只能有一个客户端打开对其进行操作,即同一时刻只能有一个用户使用它,自然这在工作当中是很不方便的,所以我们要重新为其配置一个数据库。

④Hadoop:Hive用HDFS进行存储,用MapReduce进行计算-------Hive这个数据仓库的数据存储在HDFS中,业务实际分析计算是利用MapReduce执行的。

从上面的体系结构中可以看出,在Hadoop的HDFS与MapReduce以及MySql的辅助下,Hive其实就是利用Hive解析器将用户的SQl语句解析成对应的MapReduce程序而已,即Hive仅仅是一个客户端工具,这也是为什么我们在Hive的搭建过程中没有分布与伪分布搭建的原因。(Hive就像是刘邦一样,合理的利用了张良、韩信与萧何的辅助,从而成就了一番大事!)

3、Hive的运行机制

Hive的运行机制如下图所示: 

Hive的运行机制正如图所示:创建完表之后,用户只需要根据业务需求编写Sql语句,而后将由Hive框架将Sql语句解析成对应的MapReduce程序,通过MapReduce计算框架运行job,便得到了我们最终的分析结果。

在Hive的运行过程中,用户只需要创建表、导入数据、编写Sql分析语句即可,剩下的过程将由Hive框架自动完成,而创建表、导入数据、编写Sql分析语句其实就是数据库的知识了,Hive的运行过程也说明了为什么Hive的存在大大降低了Hadoop的学习门槛以及为什么Hive在Hadoop家族中占有着那么重要的地位。

二:Hive的操作

Hive的操作对于用户来说实际上就是表的操作、数据库的操作。下面我们将围绕两个方面进行介绍:

1、Hive的基本命令.

启动hive命令行:

  1. $>hive/bin/hive 
  2.     $hive>show databases ;                              -- 显式数据库 
  3.     $hive>create database mydb ;                        -- 创建数据库 
  4.     $hive>use mydb ;                                    -- 使用库 
  5.     $hive>create table custs(id int , name string) ;    -- 建表 
  6.     $hive>desc custs ;                                  -- 查看表结构 
  7.     $hive>desc formatted custs ;                        -- 查看格式化表结构 
  8.     $hive>insert into custs(id,namevalues(1,'tom');   -- 插入数据,转成mr. 
  9.     $hive>select * from custs ;                         -- 查询,没有mr 
  10.     $hive>select * from custs order by id desc ;        -- 全排序,会生成mr. 
  11.     $hive>exit ;                                        -- 退出终端 
  12.  
  13.  
  14. 查看mysql中的元信息: 
  15.     select * from dbs ;                                 -- 存放库信息 
  16.     select * from tbls ;                                -- 存放表信息 

2、Hive表------内部表、外部表、分区表的创建

所谓内部表就是普通表,创建语法格式为: 

实际操作: 

外部表(external table)的创建语法格式为: 

注意:最后一行写到的是目录dir,文件就不用写了,Hive表会自动到dir目录下读取所有的文件file

我在实际的操作过程当中发现,location关联到的目录下面必须都是文件,不能含有其余的文件夹,不然读取数据的时候会报错。 

实际操作: 

内部表与外部表的区别:

补充:在工作中发现,对于外部表,即使hive中的表删除了,但是在HDFS中表的location仍然存在。

分区表的概念:指的是我们的数据可以分区,即按照某个字段将文件划分为不同的标准,分区表的创建是通过在创建表时启用partitioned by来实现的。

分区表的创建语法格式为: 

注意:分区表在加载数据的过程中要指定分区字段,否则会报错,正确的加载方式如下:

  1. load data local inpath ‘/usr/local/consumer.txt’ into table t1 partition (day=2) ; 

其余的操作和内部表、外部表是一样的。

实际操作: 

参考2:

  1. CREATE EXTERNAL TABLE `fdm_buffalo_3_5_task_exec_time`( 
  2.   `task_id`      int COMMENT '任务id',  
  3.   `task_version` string COMMENT '任务版本',  
  4.   `exec_time`    string COMMENT '平均执行时长'
  5. PARTITIONED BY (  
  6.   `dt` string) 
  7. ROW FORMAT DELIMITED  
  8.   FIELDS TERMINATED BY '\t'
  9.  
  10.  
  11. 实际: 
  12. hive> show create table fdm_buffalo_3_5_task_exec_time; 
  13. OK 
  14. CREATE EXTERNAL TABLE `fdm_buffalo_3_5_task_exec_time`( 
  15.   `task_id` int COMMENT '任务id',  
  16.   `task_version` string COMMENT '任务版本',  
  17.   `exec_time` string COMMENT '平均执行时长'
  18. PARTITIONED BY (  
  19.   `dt` string) 
  20. ROW FORMAT DELIMITED  
  21.   FIELDS TERMINATED BY '\t'  
  22. STORED AS INPUTFORMAT  
  23.   'org.apache.hadoop.mapred.TextInputFormat'  
  24. OUTPUTFORMAT  
  25.   'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat' 
  26. LOCATION 
  27.   'hdfs://ns5/user/dd_edw/fdm.db/fdm_buffalo_3_5_task_exec_time' 
  28. TBLPROPERTIES ( 
  29.   'mart_name'='dd_edw',  
  30.   'transient_lastDdlTime'='1555384611'
  31. Time taken: 0.036 seconds, Fetched: 17 row(s) 

3、将数据文件加载(导入)到Hive表中

在Hive中创建完表之后,我们随后自然要向表中导入数据,但是在导入数据的时候和我们的传统数据库(MySql、Oracle)是不同的:Hive不支持一条一条的用insert语句进行插入操作,也不支持update的操作。Hive表中的数据是以load的方式,加载到建立好的表中。数据一旦导入,则不可修改。要么drop掉整个表,要么建立新的表,导入新的数据。

导入数据的语法格式为: 

导入数据时要注意一下几点:

导入示例代码:(注意overwrite的用法)

  1. hive> load data local inpath "/home/dd_edw/zmy_project/task_relations.txt" overwrite into table fdm.chevrolet_buffalo_task_recusion_relations partition(dt='2019-05-28'); 
  2. Loading data to table fdm.chevrolet_buffalo_task_recusion_relations partition (dt=2019-05-28) 
  3. Moved: 'hdfs://ns5/user/dd_edw/fdm.db/chevrolet_buffalo_task_recusion_relations/dt=2019-05-28/task_relations.txt' to trash at: hdfs://ns5/user/dd_edw/.Trash/Current 
  4. Moved: 'hdfs://ns5/user/dd_edw/fdm.db/chevrolet_buffalo_task_recusion_relations/dt=2019-05-28/task_relations_copy_1.txt' to trash at: hdfs://ns5/user/dd_edw/.Trash/Current 
  5. Partition fdm.chevrolet_buffalo_task_recusion_relations{dt=2019-05-28} stats: [numFiles=1, numRows=0, totalSize=272475104, rawDataSize=0] 
  6. OK 
  7. Time taken: 3.381 seconds 
  8. hive> dfs -ls hdfs://ns5/user/dd_edw/fdm.db/chevrolet_buffalo_task_recusion_relations/*/ ; 
  9. Found 1 items 
  10. -rwxr-xr-x   3 dd_edw dd_edw  272475104 2019-05-29 20:08 hdfs://ns5/user/dd_edw/fdm.db/chevrolet_buffalo_task_recusion_relations/dt=2019-05-28/task_relations.txt 

4、Hive添加分区操作:

正确语句:

  1. hive> ALTER TABLE fdm_buffalo_3_5_task_exec_time ADD IF NOT EXISTS PARTITION (dt='2019-04-15'); 
  2. OK 
  3. Time taken: 0.059 seconds 

错误语句:

  1. hive> alter table fdm_buffalo_3_5_task_exec_time if not exists add partition (dt='2019-04-15'); 
  2. NoViableAltException(132@[]) 
  3.         at org.apache.hadoop.hive.ql.parse.HiveParser.alterTableStatementSuffix(HiveParser.java:8170) 
  4.         at org.apache.hadoop.hive.ql.parse.HiveParser.alterStatement(HiveParser.java:7635) 
  5.         at org.apache.hadoop.hive.ql.parse.HiveParser.ddlStatement(HiveParser.java:2798) 
  6.         at org.apache.hadoop.hive.ql.parse.HiveParser.execStatement(HiveParser.java:1731) 
  7.         at org.apache.hadoop.hive.ql.parse.HiveParser.statement(HiveParser.java:1136) 
  8.         at org.apache.hadoop.hive.ql.parse.ParseDriver.parse(ParseDriver.java:202) 
  9.         at org.apache.hadoop.hive.ql.parse.ParseDriver.parse(ParseDriver.java:166) 
  10.         at org.apache.hadoop.hive.ql.Driver.compile(Driver.java:411) 
  11.         at org.apache.hadoop.hive.ql.Driver.compile(Driver.java:320) 
  12.         at org.apache.hadoop.hive.ql.Driver.compileInternal(Driver.java:1372) 
  13.         at org.apache.hadoop.hive.ql.Driver.runInternal(Driver.java:1425) 
  14.         at org.apache.hadoop.hive.ql.Driver.run(Driver.java:1150) 
  15.         at org.apache.hadoop.hive.ql.Driver.run(Driver.java:1093) 
  16.         at org.apache.hadoop.hive.cli.CliDriver.processLocalCmd(CliDriver.java:241) 
  17.         at org.apache.hadoop.hive.cli.CliDriver.processCmd(CliDriver.java:191) 
  18.         at org.apache.hadoop.hive.cli.CliDriver.processLine(CliDriver.java:551) 
  19.         at org.apache.hadoop.hive.cli.CliDriver.executeDriver(CliDriver.java:969) 
  20.         at org.apache.hadoop.hive.cli.CliDriver.run(CliDriver.java:912) 
  21.         at org.apache.hadoop.hive.cli.CliDriver.main(CliDriver.java:824) 
  22.         at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
  23.         at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 
  24.         at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
  25.         at java.lang.reflect.Method.invoke(Method.java:606) 
  26.         at org.apache.hadoop.util.RunJar.run(RunJar.java:221) 
  27.         at org.apache.hadoop.util.RunJar.main(RunJar.java:136) 
  28. FAILED: ParseException line 1:43 cannot recognize input near 'if' 'not' 'exists' in alter table statement 

5、查看某个分区

  1. desc formatted bdm.bdm_dispatch_1_d_task_da partition(dt='2019-07-14'); 

三:Hive与Hbase的区别

其实从严格意义上讲,Hive与Hbase就不应该谈区别,谈区别的原因无非就是Hive与Hbase本身都涉及到了表的创建、向表中插入数据等等。所以我们希望找到Hive与Hbase的区别,但是为什么两者谈不上区别呢,原因如下:

  1. 根据上文分析,Hive从某种程度上讲就是很多“SQL—MapReduce”框架的一个封装,即Hive就是MapReduce的一个封装,Hive的意义就是在业务分析中将用户容易编写、会写的Sql语言转换为复杂难写的MapReduce程序。
  2. Hbase可以认为是hdfs的一个包装。他的本质是数据存储,是个NoSql数据库;hbase部署于hdfs之上,并且克服了hdfs在随机读写方面的缺点。

因此若要问Hive与Hbase之前的区别,就相当于问HDFS与MapReduce之间的区别,而HDFS与MapReduce两者之间谈区别意义并不大。

但是当我们非要谈Hbase与Hive的区别时,可以从以下几个方面进行讨论:

Hive和Hbase是两种基于Hadoop的不同技术–Hive是一种类SQL的引擎,并且运行MapReduce任务,Hbase是一种在Hadoop之上的NoSQL 的Key/vale数据库。当然,这两种工具是可以同时使用的。就像用Google来搜索,用FaceBook进行社交一样,Hive可以用来进行统计查询,HBase可以用来进行实时查询,数据也可以从Hive写到Hbase,设置再从Hbase写回Hive。

Hive适合用来对一段时间内的数据进行分析查询,例如,用来计算趋势或者网站的日志。Hive不应该用来进行实时的查询。因为它需要很长时间才可以返回结果。

Hbase非常适合用来进行大数据的实时查询。Facebook用Hive进行消息和实时的分析。它也可以用来统计Facebook的连接数。

 

来源:今日头条内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯