Hbase中二级索引与Phoenix二级索引实现

1、引入

HBase本身只提供基于行键和全表扫描的查询,而行键索引单一,对于多维度的查询困难。

所以我们引进一个二级索引的概念。二级索引的本质就是建立各列值与行键之间的映射关系

图解:

 

2、常见实现二级索引的方案:

HBase的一级索引就是rowkey,我们只能通过rowkey进行检索。如果我们相对hbase里面列族的列列进行一些组合查询,就需要采用HBase的二级索引方案来进行多条件的查询。

  1. MapReduce方案

  2. ITHBASE(Indexed-Transanctional HBase)方案

  3. IHBASE(Index HBase)方案

  4. Hbase Coprocessor(协处理器)方案

  5. Solr+hbase方案或 redis+hbase 方案

  6. CCIndex(complementalclustering index)方案

下面我们用代码来实现MapReduce方案与redis+hbase 方案

三、MapReduce方案实现

使用整合MapReduce的方式创建hbase索引。主要的流程如下:

1、扫描输入表,使用hbase继承类TableMapper

2、获取rowkey和指定字段名称和字段值

3、创建Put实例, value=” “, rowkey=班级,column=学号

4、使用IdentityTableReducer将数据写入索引表

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.*;
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.hadoop.hbase.mapreduce.TableMapReduceUtil;
import org.apache.hadoop.hbase.mapreduce.TableMapper;
import org.apache.hadoop.hbase.mapreduce.TableReducer;
import org.apache.hadoop.hbase.regionserver.BloomType;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;

import java.io.IOException;

/**
 * 使用整合MapReduce的方式创建hbase索引。主要的流程如下:
 * 1.1扫描输入表,使用hbase继承类TableMapper
 * 1.2获取rowkey和指定字段名称和字段值
 * 1.3创建Put实例, value=” “, rowkey=班级,column=学号
 * 1.4使用IdentityTableReducer将数据写入索引表
 */
//因为我们现在要读取的数据来自于hbase中的hfile文件,与hdfs上普通的block块文件有所区别,不能直接继承Mapper类
//要继承hbase读取数据专属的Mapper类     TableMapper
//public abstract class TableMapper<KEYOUT, VALUEOUT> extends Mapper<ImmutableBytesWritable, Result, KEYOUT, VALUEOUT>
class MyIndexMapper extends TableMapper<Text, NullWritable> {
    @Override
    protected void map(ImmutableBytesWritable key, Result value, Mapper<ImmutableBytesWritable, Result, Text, NullWritable>.Context context) throws IOException, InterruptedException {
        //ImmutableBytesWritable key --相当于是读取到一行的行键
        //Result value --相当于读取到一行多列的封装
        //获取行键
        String id = Bytes.toString(key.get());
        //获取姓名的列值
        String name = Bytes.toString(value.getValue(Bytes.toBytes("info"), Bytes.toBytes("name")));
        //将学号和姓名拼接起来给到reduce,由reduce处理并写入到到索引表中
        context.write(new Text(id + "-" + name), NullWritable.get());
    }
}

//public abstract class TableReducer<KEYIN, VALUEIN, KEYOUT> extends Reducer<KEYIN, VALUEIN, KEYOUT, Mutation>
class MyIndexReducer extends TableReducer<Text, NullWritable, NullWritable> {
    @Override
    protected void reduce(Text value, Iterable<NullWritable> values, Reducer<Text, NullWritable, NullWritable, Mutation>.Context context) throws IOException, InterruptedException {
        String string = value.toString();
        String id = string.split("-")[0];
        String name = string.split("-")[1];

        //将要添加的数据封装成Put类的对象
        Put put = new Put(Bytes.toBytes(name));
        put.addColumn(Bytes.toBytes("info"),Bytes.toBytes(id),Bytes.toBytes(""));

        context.write(NullWritable.get(), put);

    }
}

public class HBaseIndexDemo1 {
    public static void main(String[] args) throws Exception {
        //创建配置文件对象
        Configuration conf = new Configuration();
        //指定zookeeper的配置信息
        conf.set("hbase.zookeeper.quorum", "master:2181,node1:2181,node2:2181");
        //创建Job作业对象
        Job job = Job.getInstance(conf);
        job.setJobName("给学生表创建二级索引表");

        job.setJarByClass(HBaseIndexDemo1.class);
        //因为索引表的构建是建立列值与行键的映射关系,要获取所有的数据
        //scan扫描全表数据
        Scan scan = new Scan();
        //告诉输入的列值来自于哪一个列簇
        scan.addFamily(Bytes.toBytes("info"));

        //先将表名封装成一个TableName的对象
        Connection conn = ConnectionFactory.createConnection(conf);
        Admin admin = conn.getAdmin();

        //先将表名封装成一个TableName的对象
        TableName tn = TableName.valueOf("students2_index");
        if (!admin.tableExists(tn)) {
            TableDescriptorBuilder studentsIndex = TableDescriptorBuilder.newBuilder(tn);

            //使用另外一种方式创建列簇并设置布隆过滤器
            ColumnFamilyDescriptor columnFamilyDescriptor = ColumnFamilyDescriptorBuilder.newBuilder(Bytes.toBytes("info"))
                    .setBloomFilterType(BloomType.ROW).build();
            studentsIndex.setColumnFamily(columnFamilyDescriptor);
            admin.createTable(studentsIndex.build());
            System.out.println(tn + "表创建成功!!!");
        } else {
            System.out.println(tn + "表已经存在!");
        }


        //索引表是执行完MR作业后产生的
        /**
         /**
         * Use this before submitting a TableMap job. It will appropriately set up
         * the job.
         *
         * @param table  The table name to read from.
         * @param scan  The scan instance with the columns, time range etc.
         * @param mapper  The mapper class to use.
         * @param outputKeyClass  The class of the output key.
         * @param outputValueClass  The class of the output value.
         * @param job  The current job to adjust.  Make sure the passed job is
         * carrying all necessary HBase configuration.
         * @throws IOException When setting up the details fails.
         *public static void initTableMapperJob
         * (String table,Scan scan,Class<? extends TableMapper> mapper,Class<?> outputKeyClass,Class<?> outputValueClass,Job job)
         */
        TableMapReduceUtil.initTableMapperJob("students2", scan, MyIndexMapper.class, Text.class, NullWritable.class, job);

        TableMapReduceUtil.initTableReducerJob("students2_index", MyIndexReducer.class, job);

        //提交作业到集群中允许
        boolean b = job.waitForCompletion(true);
        if (b) {
            System.out.println("================== students2索引表构建成功!!!============================");
        } else {
            System.out.println("================== students2索引表构建失败!!!============================");
        }

    }
}

四、使用redis第三方的存储工具存储hbase索引

import com.shujia.utils.HBaseUtil;
import org.apache.hadoop.hbase.CompareOperator;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.*;
import org.apache.hadoop.hbase.filter.BinaryComparator;
import org.apache.hadoop.hbase.filter.ValueFilter;
import org.apache.hadoop.hbase.util.Bytes;
import redis.clients.jedis.Jedis;

import java.util.Scanner;
import java.util.Set;

/*
    使用redis第三方的存储工具存储hbase索引(本质依旧是列值与行键产生映射关系)
 */
public class HBaseWithRedisIndex {
    //1、获取hbase数据库连接对象和操作对象
    static Connection conn = HBaseUtil.CONNECTION;
    static Admin admin = HBaseUtil.ADMIN;

    //获取redis连接对象
    static Jedis jedis = new Jedis("192.168.19.100", 12346);

    public static void main(String[] args) throws Exception {
        //步骤1:在redis中构建映射关系(性别:学号)
//        buildIndexInRedis();

        //使用:先通过查询redis中性别对应的学号,拿着学号去hbase原表中查询获取结果
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入您要查询的性别:");
        String gender = sc.next();
        selectGenderFromHbase(gender);
    }

    public static void selectGenderFromHbase(String gender) throws Exception {
        if ("男".equals(gender)) {
            selectIdFromRedis(gender);
        } else if ("女".equals(gender)) {
            selectIdFromRedis(gender);
        } else {
            System.out.println("没有该性别");
        }
    }

    //单独编写一个方法查询redis
    public static void selectIdFromRedis(String gender) throws Exception {
        Table students2 = conn.getTable(TableName.valueOf("students2"));

        Set<String> ids = jedis.smembers("性别:"+gender);
        for (String id : ids) {
            Result result = students2.get(new Get(Bytes.toBytes(id)).addColumn(Bytes.toBytes("info"), Bytes.toBytes("name")));
            String name = Bytes.toString(result.getValue(Bytes.toBytes("info"), Bytes.toBytes("name")));
            System.out.println("学号:" + id + ",姓名:" + name);
        }
    }

    public static void buildIndexInRedis() throws Exception {

        //获取要构建索引的原表
        Table students2 = conn.getTable(TableName.valueOf("students2"));

        Scan scan = new Scan();
        //获取男生的学号,放入到redis中
        //创建列值过滤器
        ValueFilter filter1 = new ValueFilter(CompareOperator.EQUAL, new BinaryComparator(Bytes.toBytes("男")));
        scan.setFilter(filter1);
        ResultScanner resultScanner = students2.getScanner(scan);
        for (Result result : resultScanner) {
            //获取每一行的行键即可
            String id = Bytes.toString(result.getRow());
            //将学号以值的方式添加到redis键对应的值中
            //因为男生的学号有很多个,且不重复,所以我们在redis中采用set的数据类型存储
            jedis.sadd("性别:男", id);
        }

        //获取男生的学号,放入到redis中
        //创建列值过滤器
        ValueFilter filter2 = new ValueFilter(CompareOperator.EQUAL, new BinaryComparator(Bytes.toBytes("女")));
        scan.setFilter(filter2);
        ResultScanner resultScanner2 = students2.getScanner(scan);
        for (Result result : resultScanner2) {
            //获取每一行的行键即可
            String id = Bytes.toString(result.getRow());
            //将学号以值的方式添加到redis键对应的值中
            //因为男生的学号有很多个,且不重复,所以我们在redis中采用set的数据类型存储
            jedis.sadd("性别:女", id);
        }

    }
}

五、Phoenix二级索引

1、开启索引支持

# 在hbase-site.xml中增加如下配置

<property>
  <name>hbase.regionserver.wal.codec</name>
  <value>org.apache.hadoop.hbase.regionserver.wal.IndexedWALEditCodec</value>
</property>
<property>
    <name>hbase.rpc.timeout</name>
    <value>60000000</value>
</property>
<property>
    <name>hbase.client.scanner.timeout.period</name>
    <value>60000000</value>
</property>
<property>
    <name>phoenix.query.timeoutMs</name>
    <value>60000000</value>
</property>


# 同步到所有节点
scp hbase-site.xml node1:`pwd`
scp hbase-site.xml node2:`pwd`

# 修改phoenix目录下的bin目录中的hbase-site.xml
<property>
    <name>hbase.rpc.timeout</name>
    <value>60000000</value>
</property>
<property>
    <name>hbase.client.scanner.timeout.period</name>
    <value>60000000</value>
</property>
<property>
    <name>phoenix.query.timeoutMs</name>
    <value>60000000</value>
</property>

-------------------------------------------------------------------------------------------------------------------------
# 启动hbase
start-hbase.sh
# 重新进入phoenix客户端
sqlline.py master,node1,node2

2、索引的种类及其实现方式

2.1、全局索引

        全局索引适合读多写少的场景。如果使用全局索引,读数据基本不损耗性能,所有的性能损耗都来源于写数据。数据表的添加、删除和修改都会更新相关的索引表(数据删除了,索引表中的数据也会删除;数据增加了,索引表的数据也会增加)  

        注意: 对于全局索引在默认情况下,在查询语句中检索的列如果不在索引表中,Phoenix不会使用索引表将,除非使用hint

手机号 进入网格的时间 离开网格的时间 区县编码 经度 纬度 基站标识 网格编号 业务类型

# 创建DIANXIN.sql
CREATE TABLE IF NOT EXISTS DIANXIN (
     mdn VARCHAR ,
     start_date VARCHAR ,
     end_date VARCHAR ,
     county VARCHAR,
     x DOUBLE ,
     y  DOUBLE,
     bsid VARCHAR,
     grid_id  VARCHAR,
     biz_type VARCHAR, 
     event_type VARCHAR , 
     data_source VARCHAR ,
     CONSTRAINT PK PRIMARY KEY (mdn,start_date)
) column_encoded_bytes=0;

# 上传数据DIANXIN.csv

# 导入数据
psql.py master,node1,node2 DIANXIN.sql DIANXIN.csv

# 创建全局索引
CREATE INDEX DIANXIN_INDEX ON DIANXIN ( end_date );

# 查询数据 ( 索引未生效)
select * from DIANXIN where end_date = '20180503154014';

# 强制使用索引 (索引生效) hint  语法糖
select /*+ INDEX(DIANXIN DIANXIN_INDEX) */  * from DIANXIN where end_date = '20180503154014';

select /*+ INDEX(DIANXIN DIANXIN_INDEX) */  * from DIANXIN where end_date = '20180503154014'  and start_date = '20180503154614';

# 取索引列,(索引生效)
select end_date from DIANXIN where end_date = '20180503154014';

# 创建多列索引
CREATE INDEX DIANXIN_INDEX1 ON DIANXIN ( end_date,COUNTY );

# 多条件查询 (索引生效)
select end_date,MDN,COUNTY from DIANXIN where end_date = '20180503154014' and COUNTY = '8340104';

# 查询所有列 (索引未生效)
select  * from DIANXIN where end_date = '20180503154014'  and COUNTY = '8340104';

# 查询所有列 (索引生效)
select /*+ INDEX(DIANXIN DIANXIN_INDEX1) */ * from DIANXIN where end_date = '20180503154014' and COUNTY = '8340104';

# 单条件  (索引未生效)
select end_date from DIANXIN where  COUNTY = '8340103';
# 单条件  (索引生效) end_date 在前
select COUNTY from DIANXIN where end_date = '20180503154014';

# 删除索引
drop index DIANXIN_INDEX on DIANXIN;

2.2、本地索引

        本地索引适合写多读少的场景,或者存储空间有限的场景。和全局索引一样,Phoenix也会在查询的时候自动选择是否使用本地索引。本地索引因为索引数据和原数据存储在同一台机器上,避免网络数据传输的开销,所以更适合写多的场景。由于无法提前确定数据在哪个Region上,所以在读数据的时候,需要检查每个Region上的数据从而带来一些性能损耗。

       注意:对于本地索引,查询中无论是否指定hint或者是查询的列是否都在索引表中,都会使用索引表。

# 创建本地索引
CREATE LOCAL INDEX DIANXIN_LOCAL_IDEX ON DIANXIN(grid_id);

# 索引生效
select grid_id from dianxin where grid_id='117285031820040';

# 索引生效
select * from dianxin where grid_id='117285031820040';

 

2.3、覆盖索引

   覆盖索引是把原数据存储在索引数据表中,这样在查询时不需要再去HBase的原表获取数据就,直接返回查询结果。

   注意:查询是 select 的列和 where 的列都需要在索引中出现。

# 创建覆盖索引
CREATE INDEX DIANXIN_INDEX_COVER ON DIANXIN ( x,y ) INCLUDE ( county );

# 查询所有列 (索引未生效)
select * from DIANXIN where x=117.288 and y =31.822;

# 强制使用索引 (索引生效)
select /*+ INDEX(DIANXIN DIANXIN_INDEX_COVER) */ * from DIANXIN where x=117.288 and y =31.822;

# 查询索引中的列 (索引生效) mdn是DIANXIN表的RowKey中的一部分
select x,y,county from DIANXIN where x=117.288 and y =31.822;
select mdn,x,y,county from DIANXIN where x=117.288 and y =31.822;

# 查询条件必须放在索引中  select 中的列可以放在INCLUDE (将数据保存在索引中)
select /*+ INDEX(DIANXIN DIANXIN_INDEX_COVER) */ x,y,count(*) from DIANXIN group by x,y;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/572132.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

go版本1.16.5 运行项目出现undefined: math.MaxInt报错

问题描述 go版本 go1.16.5 项目引用了 包go-sqlite3 v1.14.17 github.com/mattn/go-sqlite3 v1.14.17运行报错 # github.com/mattn/go-sqlite3 D:\GoPATH\pkg\mod\github.com\mattn\go-sqlite3v1.14.17\sqlite3_opt_serialize.go:41:26: undefined: math.MaxInt原因分析&…

离散数学之一阶逻辑基本概念与等值演算思维导图+大纲笔记(期末复习,考研,学习笔记,知识点总结)

大纲笔记 基本概念 一阶逻辑命题符号化 个体词 个体常项 个体变项 个体域 个体总域 谓词 谓词常项 谓词变项 零元谓词 特性谓词 引入规则 量词 全称量词 存在量词 一阶逻辑1公式及解释 基本概念 原子公式 谓词公式 自由变元与约束变元 自由变元 换名规则 约束变元 带入规则 闭…

强制内容在一行显示

强制内容在一行显示 .one {white-space: nowrap;overflow: hidden;text-overflow: ellipsis; /* 可选&#xff0c;当内容超出一行时&#xff0c;用省略号表示 */ }效果

构建代理IP池并自动测试可用性的爬虫实现

目录 前言 一、认识代理IP 1. 隐藏真实IP地址 2. 提高爬虫效率 二、爬取代理IP 三、测试代理IP可用性 1. 发起HTTP请求 2. 超时检测 3. 循环请求 四、构建代理IP池 五、总结 前言 随着互联网的发展&#xff0c;网络爬虫在数据采集、搜索引擎、信息监控等领域发挥着…

vue2和vue3浏览器兼容性对比

一、Vue2.0不支持IE8, 因为Vue使用了IE8无法模拟的ECMAScript 5 特性,但它支持所有兼容ECMAScript 5 的浏览器。 二、Vue3.0 不支持 IE11 及以下版本。兼容ECMAScript 5的浏览器

铝基碳化硅复合材料(AlSiC)可用于制造火星车 行业发展前景较好

铝基碳化硅复合材料&#xff08;AlSiC&#xff09;可用于制造火星车 行业发展前景较好 铝基碳化硅复合材料&#xff08;AlSiC&#xff09;又称铝基碳化硅颗粒增强复合材料&#xff0c;指由铝和碳化硅复合而成的高性能材料。铝基碳化硅复合材料具有耐腐蚀、高温稳定性好、轻量化…

机器学习笔记(二)回归

一、线性回归 线性回归是一种用于预测的统计方法&#xff0c;特别适用于连续值预测。&#x1f4c8;线性回归通过最小化误差的平方和来寻找一个线性关系&#xff0c;用于预测一个变量&#xff08;因变量&#xff09;基于一个或多个其他变量&#xff08;自变量&#xff09;的值。…

02 贪吃蛇

前言 呵呵 这是不知道 在哪里看到的 别人做的一个贪吃蛇 因此 也把我 之前的 贪吃蛇 移植上来了 当然 这个不过是为了 简单的入门了解, 呵呵 然后 c版本的贪吃蛇 需要先移植成 c 版本, 然后 再根据 单片机相关 设计调整 比如 led 点阵的输出, 比如 c99 语法的一些不兼容…

Power BI数据刷新 - 网关 数据源凭据详解

众所周知&#xff0c;如果在Power BI云服务中设置数据源自动刷新&#xff0c;有两种方式供你选择, 分别是&#xff1a; Gateway and cloud connections&#xff08;网关和云连接&#xff09;&#xff1b;Data Source Credentials&#xff08;数据源凭据&#xff09;&#xff1…

分类算法——模型评估(八)

1混淆矩阵 在分类任务下&#xff0c;预测结果与正确标记之间存在四种不同的组合&#xff0c;构成混淆矩阵&#xff08;适用于多分类&#xff09; TP True Possitive FN False Negative 2精确率&#xff08;Precision&#xff09;与召回率&#xff08;Recall&#xff09; 精…

文献速递:肺癌早期诊断---利用低剂量CT扫描的三维概率深度学习系统用于肺癌的检测与诊

Title 题目 A 3D Probabilistic Deep Learning System forDetection and Diagnosis of Lung Cancer Using Low-Dose CT Scans 利用低剂量CT扫描的三维概率深度学习系统用于肺癌的检测与诊 01文献速递介绍 肺癌既是最常见的癌症之一&#xff0c;也是导致癌症死亡的主要原因之…

IDEA 全局查找 ctrl + shift + F 快捷键失效

全局查找&#xff1a;ctrl shift F 需要关闭微软输入法简体/繁体切换&#xff0c;不然被占用了无效 (装了搜狗输入法的同理,找一下是不是这个快捷键冲突了 ) 另外还有 IDEA 中 重构变量名 &#xff1a;shift F6 需要关闭微软输入法最新版本 ( 使用以前版本的微软输入法就没…

IPv4 NAT(含Cisco配置)

IPv4 NAT&#xff08;含Cisco配置&#xff09; IPv4私有空间地址 类RFC 1918 内部地址范围前缀A10.0.0.0 - 10.255.255.25510.0.0.0/8B172.16.0.0 - 172.31.255.255172.16.0.0/12C192.168.0.0 - 192.168.255.255192.168.0.0/16 这些私有地址可在企业或站点内使用&#xff0c…

【项目】仿muduo库One Thread One Loop式主从Reactor模型实现高并发服务器(TcpServer板块)

【项目】仿muduo库One Thread One Loop式主从Reactor模型实现⾼并发服务器&#xff08;TcpServer板块&#xff09; 一、思路图二、模式关系图三、定时器的设计1、Linux本身给我们的定时器2、我们自己实现的定时器&#xff08;1&#xff09;代码部分&#xff08;2&#xff09;思…

机器学习周记(第三十五周:语义分割)2024.4.15~2024.4.21

目录 摘要 ABSTRACT 1 语义分割基本概念 1.1 数据集格式 ​编辑 1.2 语义分割评价指标 1.3 语义分割标注工具 2 转置卷积 3 FCN网络结构基本原理 摘要 本周主要学习了语义分割的基本概念及其在计算机视觉领域中的应用。了解了语义分割的几种经典网络&#xff0c;如全卷…

绝地求生【商城更新】WIA联名上架//专属商店下架

大家好&#xff0c;我是闲游盒. 本周商城将在4.24&#xff08;周三&#xff09;更新&#xff0c;商城内容更新如下&#xff1a; 上架物品 ▲W.I.A联名皮肤大礼包 小礼包如下&#xff1a; 包含3套衣服以及MINI、DBS的联名皮肤&#xff0c;3个头饰还挺有特色的&#xff0c;你喜欢…

Edge浏览器下载文件提示 “无法安全下载” 的解决方法

提示如下&#xff1a; 虽然我们可以通过 "保留" 进行下载&#xff0c;但是每次需要选择&#xff0c;比较麻烦 解决方法&#xff1a; 1、打开注册表 HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft 2、创建2个 "项" Edge\InsecureContentAllowedForUrls…

目前主流的负载均衡器

客户端负载均衡器 Ribbon 客户端根据自己的请求进行负载均衡Ribbon就属于这一类 Ribbon可以帮助你在调用这些服务时进行负载均衡。具体来说&#xff0c;当你通过Ribbon进行服务调用时&#xff0c;它可以根据配置的负载均衡策略&#xff08;如轮询、随机、最少并发数等&#xff…

机器学习笔记(一)基本概念

一、浅谈机器学习 1.1 机器学习简介 机器学习目的并不是为了得到最后的运算结果&#xff0c;而是对计算过程进行分析&#xff0c;总结出一套运算的规则。只要数据量足够多&#xff0c;运算规则就越准确。最后可以根据这套规则对没有通过验证的数据进行预算&#xff0c;得到预算…

Linux编译和NXP官方系统移植

文章目录 一、Linux安装环境配置二、Linux编译流程三、单个.dtb文件编译方法1.修改顶层makefile2.编译设备树文件3.验证 四、NXP官方Linux系统移植1.将NXP官方Linux系统导入到Ubuntu系统中2.解压系统3.编译系统4.验证5.在NXP官方系统中添加自己的板子 五、 CPU 主频和网络驱动修…