MariaDB开窗函数(开窗函数 mysql)
sinye56 2024-09-22 08:25 6 浏览 0 评论
在使用GROUP BY子句时,总是需要将筛选的所有数据进行分组操作,它的分组作用域是整张表。分组以后,为每个组只返回一行。而使用基于窗口的操作,类似于分组,但却可以对这些"组"(即窗口)中的每一行进行计算,所以可以为每"组"返回多行。
窗口函数也称为分区函数,在Oracle中称为分析函数,因为开窗函数是对分区中的数据进行个各种分析、计算。
MySQL直到MySQL 8才千呼万唤般开始支持窗口函数。MariaDB 10.2之后开始支持window function。
本文将简单介绍开窗函数的使用方法,并给出一些经典示例,同时还会给出使用子查询实现开窗函数的功能。由此来说明开窗函数相比子查询的简洁、高效率。
1.1 窗口和开窗函数简介
在如图所示的成绩表中,包含了6名学生的3科成绩,共18行记录。按照学号sid进行划分,每名学生都可以被看成是一个窗口(或称为分区),18行成绩共有6个窗口。可以基于每个窗口中的数据进行排序和聚合操作,如在 sid=1 的窗口进行一次升序排序,编号从1开始。当到其他窗口时,编号又重新从1开始。当然也可以按课程定义窗口,有3门课程,因此可以分为3个窗口。
窗口函数的特征是使用OVER()关键字。"开窗函数"这一名词描述了窗口变化后重新打开其它窗口进行计算的动作。窗口计算主要是对每组数据进行排序或聚合计算,因此开窗函数可以分为排名开窗函数和聚合开窗函数。
之所以提出窗口的概念,是因为这种基于窗口或分区的重新计算能简化很多问题。在不支持该技术时,很多情况下处理基于窗口重新计算的问题时,语句的编写相对复杂许多。窗口的提出,提供了一种简单而又高效的问题解决方式。在本文中也会演示不使用这些基于窗口计算的替代语句,熟悉这些替代语句后,才能更好的体会这种技术的简单和高效。
1.2 OVER()语法和执行位置
在逻辑执行顺序上,OVER()子句的执行位置在WHERE、GROUP BY和HAVING子句之后,在ORDER BY子句之前。如下:
SELECT (11)<DISTINCT> (5)select_list (9)<OVER()>
( 1)FROM
( 3) JOIN
( 2) ON
( 4)WHERE
( 6)GROUP BY
( 7)WITH ROLLUP
( 8)HAVING
(10)ORDER BY
(12)LIMIT
因此,where子句无法筛选来自开窗计算得到的结果集。
OVER()子句的使用语法如下:
function (expression) OVER (
[ PARTITION BY expression_list ]
[ ORDER BY order_list ] )
function:
A valid window function
expression_list:
expression | column_name [, expr_list ]
order_list:
expression | column_name [ ASC | DESC ] [, ... ]
MariaDB支持以下window function:
- 排名函数:ROW_NUMBER(),RANK(),DENSE_RANK(),PERCENT_RANK(),CUME_DIST(),NTILE()
- 聚合函数:COUNT(),SUM(),AVG(),BIT_OR(),BIT_AND(),BIT_XOR()
- 不支持带有DISTINCT的聚合函数,例如COUNT(DISTINCT X)
- 其他一些窗口分析函数,例如lag(),lead()。具体见官方手册。
PARTITION BY子句用于划分窗口(分区),也就是另类的GROUP BY。如果不指定PARTITION BY子句,则默认整张表是一个分区,即对所有行进行窗口函数的计算。这里的所有行不是FROM后面表的所有行,而是经过WHERE、GROUP BY、和HAVING运行之后的所有行。
ORDER BY子句用于对分区内的行进行排序。在MariaDB中可以省略该子句,表示不对分区内数据做任何排序。
在SQL Server中ORDER BY不可省略,SQL Server认为无顺序的区内数据由于不知道顺序而无法使用开窗函数。实际上,SQL Server通过特殊的ORDER BY子句,也能实现不对分区做任何排序,例如 over(order by (select 1)) ,其中1可以替换为任意其他常量。
无论如何,over()中不使用order by子句的结果中,顺序是不可预测的,因此在涉及任何排名的时候,都建议使用order by进行排序,除非你知道自己在做什么。
之所以不支持带有DISTINCT的聚合函数,是因为DISTINCT的执行过程在OVER()之后。开窗之后再DISTINCT没有意义,且消耗额外的资源。如果想先去重再OVER(),可以使用GROUP BY替代DISTINCT的功能。
1.3 row_number()对分区排名
row_number()函数用于给每个窗口内的行排名,且排名连续不断开的。例如,2个学生90分,一个学生89分,那么两个90分的学生将给定排名1和2,89分的学生给定排名3。至于谁是1谁是2,由物理存储顺序决定,也就是说当排名依据大小重复时,row_number()的排名将是不可预测的。
给定tscore表和相关数据:每个sid有3门课程以及对应的成绩,共6个sid
create or replace table tscore(sid int,subject char(10),score int);
insert into tscore values
(1,'Java',74),(1,'Linux',67),(1,'SQL',57),
(2,'Java',67),(2,'Linux',63),(2,'SQL',68),
(3,'Java',90),(3,'Linux',79),(3,'SQL',82),
(4,'Java',50),(4,'Linux',68),(4,'SQL',59),
(5,'Java',98),(5,'Linux',65),(5,'SQL',67),
(6,'Java',66),(6,'Linux',96),(6,'SQL',95);
select * from tscore;
+------+---------+-------+
| sid | subject | score |
+------+---------+-------+
| 1 | Java | 74 |
| 1 | Linux | 67 |
| 1 | SQL | 57 |
| 2 | Java | 67 |
| 2 | Linux | 63 |
| 2 | SQL | 68 |
| 3 | Java | 90 |
| 3 | Linux | 79 |
| 3 | SQL | 82 |
| 4 | Java | 50 |
| 4 | Linux | 68 |
| 4 | SQL | 59 |
| 5 | Java | 98 |
| 5 | Linux | 65 |
| 5 | SQL | 67 |
| 6 | Java | 66 |
| 6 | Linux | 96 |
| 6 | SQL | 95 |
+------+---------+-------+
按照sid分区,计算出每个sid 3科成绩的分数排名。例如sid=1的学生,Java课程分数最高,Linux课程次之,SQL分数最低,所以给定排名Java:1、Linux:2、SQL:3。sid=2的学生分数从高到低依次是SQL、Java、Linux,给定排名SQL:1、Java:2、Linux:3。依次类推。
由于是按照sid分区,所以over()子句中使用 partition by sid ,由于每个分区内部按照score降序排序,因此over()子句中使用 order by score desc 。所以,完整的SQL语句如下:
select
row_number() over(partition by sid order by score desc) as rnum,
sid,
subject,
score
from tscore;
从查询结果中,可以看到每个sid都按照score的高低为相关课程给定了排名号。但是,最后返回的结果却不那么易读,每个sid对应的rnum的顺序是乱的。因此,如果为了易读性,可以考虑在select语句中使用order by子句,对sid和rnum进行排序。如下:
select
row_number() over(partition by sid order by score desc) as rnum,
tscore.*
from tscore
order by sid,rnum;
如何使用子查询的方式实现以上row_number()的排名效果?参考如下语句:
select
/* 使用row_number() */
row_number() over(partition by t1.sid order by t1.score desc) as rnum1,
/* 使用子查询 */
(select count(*)+1 from tscore t2 where t2.sid=t1.sid and t2.score>t1.score) as rnum2,
t1.*
from tscore t1
order by sid,rnum1;
如果窗口中排序依据score的值有重复呢?row_number()如何为它们排名?如何使用子查询实现row_number()相同的效果?
/* 给定score重复的值 */
create table tscore_tmp like tscore;
insert into tscore_tmp select * from tscore;
update tscore_tmp set score=67 where sid=1 and subject='Java';
此时sid=1的学生Java和Linux两课程的分数都是67。
select
/* 使用row_number() */
row_number() over(partition by t1.sid order by t1.score desc) as rnum1,
/* 使用子查询 */
(select count(*)+1 from tscore_tmp t2 where t2.sid=t1.sid and t2.score>t1.score) as rnum2,
t1.*
from tscore_tmp t1
order by sid,rnum1;
从结果中可看出row_number()对重复值会继续向后排名。但上面的子查询却并非如此,其实读一读子查询语句就能明白为何如此。
那么如何使用子查询实现row_number()相同的结果呢?也简单,只需添加一个决胜条件即可。
select
/* 使用row_number() */
row_number() over(partition by t1.sid order by t1.score desc) as rnum1,
/* 使用子查询 */
(select count(*)+1 from tscore_tmp t2
where t2.sid=t1.sid
and (t2.score>t1.score
or (t2.score=t1.score and t2.subject>t1.subject))) as rnum2,
t1.*
from tscore_tmp t1
order by sid,rnum1;
尽管rnum1和rnum2的排名结果不一样,但这无所谓,只要能为重复值排名实现row_number()函数的效果即可。
1.4 rank()和dense_rank()
前面介绍了ROW_NUMBER(),ROW_NUMBER()的作用更像是用于编号而不是排名。例如,前面将sid=1的学生的Java课程的score改为67后,由于Java和Linux两门课程分数都是67,使用ROW_NUMBER()时得到的结果就有两种方案可供选择:一种是Java排第一位,Linux排第二位,另一种是Java第二位而Linux第一位。这两种方案都是可能的,但是正因为如此,它具有不确定性。
相比于编号,排名则具有确定性,相同的值总是被分配相同的排名值。Java和Linux都是67分,它们应当都排在第一位,也就是并列第一位。但是它们接下来的SQL课程的排名值呢?是2还是3?SQL课程前面已经有两门课程排在前面,那么SQL应该排在第3位,但是从Java和Linux并列排第一位的角度来看,它们之后的SQL应当是第二位。
MariaDB中使用RANK()和DENSE_RANK()来对应这两种排名方式,RANK()的排名方式是SQL课程的排序值是第3位,DENSE_RANK()则是第2位。DENSE_RANK()的排名方式称之为密集排名,因为它的名次之间没有间隔。
例如,下面的语句中使用ROW_NUMBER()、RANK()和DENSE_RANK()三种排名函数作比较。可以看到ROW_NUMBER()、RANK()和DENSE_RANK()三者的区别。
select t.*,
/* 使用ROW_NUMBER()的方式排名 */
row_number() over(partition by sid order by score desc) as rnum,
/* 使用RANK()的方式排名 */
rank() over(partition by sid order by score desc) as rank,
/* 使用DENSE_RANK()的方式排名 */
dense_rank() over(partition by sid order by score desc) as dense_rank
from tscore_tmp t
order by t.sid,rnum;
如果使用子查询实现rank()和dense_rank()的排名效果,参考如下语句:
也可以使用子查询的方式实现排名计算。参考下面的语句。ROW_NUMBER()的子查询实现方式前文已经介绍过。相比ROW_NUMBER(),RANK()的实现只需要比较内外两表t1和t2的score大小即可,而DENSE_RANK()则需要去除重复的score值,使用 COUNT(DISTINCT score) 实现。
select t1.*,
/* 使用ROW_NUMBER()的方式排名 */
(select count(*) + 1 from tscore_tmp AS t2
where t2.sid = t1.sid
and (t2.score > t1.score
or (t2.score = t1.score and t2.subject > t1.subject))) as rnum,
/* 使用RANK()方式排名 */
(select count(*) + 1 from tscore_tmp t2
where t2.sid = t1.sid
and t2.score > t1.score) as rank,
/* 使用DENSE_RANK()方式排名 */
(select count(distinct score) + 1 from tscore_tmp t2
where t2.sid = t1.sid
and t2.score > t1.score) as dense_rank
from tscore_tmp t1
order by sid,rnum;
1.5 percent_rank()和cume_dist()
percent_rank()函数用于计算分组中某行的相对排名。
cume_dist()函数用于计算分组中某排名的相对比重。
percent_rank()的计算方式:(窗口中rank排名-1)/(窗口行数-1)
cume_dist()的计算方式:(窗口中小于或等于当前行的行数)/窗口行数,即(<=当前rank值的行数)/窗口行数通过这样的相对位置计算,我们可以获取分区中最前、中间和最后的排名。
仍然使用上面的tscore_tmp表的数据做测试。
select
t1.*,
row_number() over(partition by sid order by score desc) as rnum,
rank() over(partition by sid order by score desc) as rank,
percent_rank() over(partition by sid order by score desc) as pct_rank,
cume_dist() over(partition by sid order by score desc) as cume_dist
from tscore_tmp t1
order by sid,rnum;
其中:
- pct_rank列是根据每个窗口中,rank列的值计算的。例如sid=1,score=67的两行记录,它们的rank值都是1,窗口中的行数位3,所以计算方式为(1-1)/(3-1)=0。
- cume_dist列计算的是每个窗口中某个rank值所占排名比重。例如sid=1,score=67的两行记录,这两行的rank值都为1,窗口中3行,所以计算方式为2/3=0.67。
如果不进行分区。
select
t1.*,
row_number() over(order by score desc) as rnum,
rank() over(order by score desc) as rank,
percent_rank() over(order by score desc) as pct_rank,
cume_dist() over(order by score desc) as cume_dist
from tscore_tmp t1
order by rnum;
以rnum=10那一行记录为例。该行rank=9,所以:
- pct_rank=(9-1)/(18-1)=8/17=0.47
- cume_dist=12/18=0.67
即使我们所取的行为rnum=10,但rnum=11和rnum=12的rank值也都为9,所以cume_dist的分子为12。即分区中(所有行)小于或等于rank=9的行共有12行。
因此,percent_rank()函数计算的是分区中某个rank排名的相对位置,cume_dist()函数计算的是分区中某个rank排名在分区中的比重。
1.6 ntile()数据分组
NTILE()的功能是进行"均分"分组,括号内接受一个代表要分组组数量的参数,然后以组为单位进行编号,对于组内每一行数据,NTILE都返回此行所在组的组编号。简单的说就是NTILE函数将每一行数据关联到组,并为每一行分配一个所属组的编号。
假设一个表的某列值为1到10的整数,要将这10行分成两组,则每个组都有5行,表示方式为NTILE(2)。如果表某列是1到11的整数,这11行要分成3组的表示方式为NTILE(3),但是这时候无法"均分",它的分配方式是先分成3组,每组3行数据,剩下的两行数据从前向后均分,即第一组和第二组都有4行数据,第三组只有3行数据。
可以使用上述方法计算每组中记录的数量,但是要注意分组的时候是按指定顺序分组的。例如1到11的整数分3组时,三个组的值分别是(1、2、3、4)、(5、6、7、8)和(9、10、11),而不是真的将均分后剩下的两个值10、11插会前两组,即(1、2、3、10)、(4、5、6、11)、(7、8、9)是错误的分组。
下面的语句指定将tscore表按score的升序排列分成4组,mark值从最低到最高共18个值,NTILE(4)的结果是前2组有5行数据,后2组只有4行数据。
SELECT
tscore.*,
row_number() over (ORDER BY score) AS rnum,
ntile(4) over (ORDER BY score) AS ntile
FROM tscore
ORDER BY rnum;
在进行NTILE()函数分组时,逻辑上会依赖ROW_NUMBER()函数。例如上面的示例,逻辑上先进行ROW_NUMBER()编号,要查询的共有18行,请求分成4组,那么编号1到5的行分配到第一组,6到10分配到第二组,依此类推,直到最后的4行被分配结束。
上面的示例是对整张表进行NTILE()操作,也可以先分区,再在每个分区中进行NTILE()。例如,对tscore表,按subject分成3个区,然后按每门课程分成高低两组。可以看出,每个区有6个学生的成绩,分成2组,每组3行数据。
select
t.*,
row_number() over(partition by subject order by score desc) as rnum,
case ntile(2) over(partition by subject order by score desc)
when 1 then 'higher score'
when 2 then 'lower score'
end as ntile
from tscore t
order by subject,rnum;
1.7 取相邻行数据:lag()函数和lead()函数
lag()和lead()函数可以在同一次查询中取出同一字段的前N行的数据(lag)和后N行的数据(lead)作为独立的列。
这种操作可以代替表的自联接,并且lag()和lead()有更高的效率。
语法:
LAG (expr[, offset]) OVER (
[ PARTITION BY partition_expression ]
< ORDER BY order_list >
)
LEAD (expr[, offset]) OVER (
[ PARTITION BY partition_expression ]
[ ORDER BY order_list ]
)
其中offset是偏移量,表示取出当前行向前或向后偏移N行后的行,默认值为1。
例如某个分区中order by排序后,当前行是第3行,lag(id,2)表示取出当前分区中的第1行(3-2),所取内容为id字段。
如以下示例:对subject分区,分区中按照score降序排序
select
t.subject,t.score,
row_number() over(partition by subject order by score desc) as rnum,
lag(sid,1) over(partition by subject order by score desc) as lag,
t.sid,
lead(sid,1) over(partition by subject order by score desc) as lead
from tscore t
order by subject,rnum;
以subject='Java'分区为例:
- 对于rnum=1的行,它表示score最高,lag(sid,1)表示取该行前一行的sid字段,由于没有前一行,所以lag_id的值为NULL,lead(sid,1)表示取该行后一行的sid字段,该行后一行为rnum=2的行,对应sid=3,所以lead_id的值为3。
- 对于rnum=2的行,按照score排序,它的前一行为rnum=1的行,对应sid=5,所以lag_id的值为5。它的后一行为rnum=3的行,对应sid=1,所以lead_id的值为1。
依次类推。
1.8 窗口聚合函数
聚合函数的要点就是对一组值进行聚合,聚合函数传统上一直以GROUP BY查询作为操作的上下文。对数据进行分组以后,查询为每个组只返回一行。而使用窗口聚合函数,以窗口作为操作对象,不再使用GROUP BY分组后的组作为操作对象。
由于开窗函数运行在逻辑上比较后执行的SELECT阶段,不像GROUP BY的逻辑执行阶段比较靠前,因此很多操作比GROUP BY方便的多。比如可以在SELECT选择列表中随意选择返回列,这样就能够同时返回某一行的数据列和聚合列,也就是说可以为非分组数据进行聚合计算。甚至如果没有分组后的HAVING筛选子句时,可以使用聚合窗口函数替代GROUP BY分组,所做的仅仅是将GROUP BY替换为PARTITION BY分组。
在进行窗口聚合计算时,OVER()子句中不再要求ORDER BY子句,因此,使用方法简化为如下:
OVER([PARTITION BY expression])
OVER()括号内的内容省略时表示对所有筛选后的行数据进行聚合。
下面的语句进行了不分区(整张表作为输入数据)和分区的平均分计算。
select
t.*,
avg(score) over() as sum_avg,
avg(score) over(partition by sid) as sid_avg
from tscore t;
如果需要使用子查询的方式达到和示例一样的结果,则需要使用联接的方式。
要计算sum_avg这一列,参考下面的语句:
select t1.*,t2.sum_avg
from tscore t1
cross join
(select avg(score) as sum_avg from tscore) as t2;
由于"sum_avg"是全部学生所有课程分数的聚合计算,它不需要先分组,因此可以将 AVG(score) OVER() 理解成子查询 SELECT AVG(score) FROM tscore ,但是它们在性能上是有差距的。
要计算"sid_avg"这一列,参考下面的语句:
select t1.*,t3.sid_avg
from tscore t1
left join (select sid,avg(score) as sid_avg from tscore
group by sid) as t3
on t3.sid=t1.sid;
将上述两个子查询联接,就得到与使用OVER()子句相同的返回结果。参考下面的语句。
select t1.*,t2.sum_avg,t3.sid_avg
from tscore t1
cross join (select avg(score) as sum_avg from tscore) t2
left join (select sid,avg(score) as sid_avg from tscore
group by sid) as t3
on t1.sid=t3.sid;
可以看出,使用OVER()子句比使用联接的方式简洁了许多,并且当语句中包含多个分区聚合时(示例中包含两个分区聚合操作),使用OVER()子句拥有更大的优势,因为使用联接的方式会涉及到多个联接,将会多次扫描需要联接的表。
使用OVER()子句另一个优点在于可以在表达式中混合使用基本列和聚合列值,而使用group by分组聚合时这是不允许的。下面两条语句在返回结果上等价的,第一条语句使用OVER()子句,第二条语句则使用联接的方式。
select t1.*,
avg(score) over() as sum_avg,
score - avg(score) over() as diff_avg
from tscore t1;
/* 使用联接的方式 */
select t1.*,sum_avg,score - t2.sum_avg as diff_avg
from tscore t1
cross join (select avg(score) as sum_avg from tscore) as t2;
对于在相同的分区进行的多种聚合计算,不会影响性能。例如,下面第一条语句仅包含一个OVER()子句,而第二条语句包含4个OVER()子句,但是它们的性能几乎是一样的。
SELECT t1.*,
AVG(score) OVER(PARTITION BY sid)
FROM tscore t1
/* 下面的查询和上面的查询性能一样 */
SELECT t1.*,
AVG(score) OVER(PARTITION BY sid) AS Avgscore,
SUM(score) OVER(PARTITION BY sid) AS Sumscore,
MAX(score) OVER(PARTITION BY sid) AS Maxscore,
MIN(score) OVER(PARTITION BY sid) AS Minscore
FROM tscore t1;
第二条语句使用子查询的替代语句如下。
select t1.*,Avgscore,Sumscore,Maxscore,Minscore
from tscore t1
left join (select sid,
AVG(score) Avgscore,
SUM(score) Sumscore,
MAX(score) Maxscore,
MIN(score) Minscore
from tscore
group by sid) as t2
on t1.sid=t2.sid;
1.9 开窗函数的性能
使用窗口函数往往效率会比一般的SQL语句高的多的多,特别是数据较大时。以下是一个性能差异比较统计结果:其中regularSQL指的是使用了一个相关子查询实现需求的SQL语句。(仅为说明性能差距,不具有代表性)
从表中可以看出,随着行数每增大10倍,regularSQL和regularSQL+index的时间都成100倍增加,而开窗函数计算的时间相比它们则少的多。
此外,一个SQL语句中如果使用了多个OVER()子句,这些OVER()子句的内容完全一致,那么很多时候只会做一次分区,这一个分区可以提供给多个开窗函数计算分析。正如上窗口聚合函数中所说:对于在相同的分区进行的多种聚合计算,不会影响性能。
总而言之,窗口函数为编写SQL语句带来了极大的便利性,且性能优越。如果能使用窗口函数解决问题,应尽量使用窗口函数。
转载出处:https://www.cnblogs.com/f-ck-need-u/p/8945248.html
相关推荐
- RHEL8和CentOS8怎么重启网络
-
本文主要讲解如何重启RHEL8或者CentOS8网络以及如何解决RHEL8和CentOS8系统的网络管理服务报错,当我们安装好RHEL8或者CentOS8,重启启动网络时,会出现以下报错:...
- Linux 内、外网双网卡路由配置
-
1.路由信息的影响Linux系统中如果有多张网卡的情况下,如果路由信息配置不正确,...
- Linux——centos7修改网卡名
-
修改网卡名这个操作可能平时用不太上,可作为了解。修改网卡默认名从ens33改成eth01.首先修改网卡配置文件名(建议将原配置文件进行备份)...
- CentOS7下修改网卡名称为ethX的操作方法
-
?Linux操作系统的网卡设备的传统命名方式是eth0、eth1、eth2等,而CentOS7提供了不同的命名规则,默认是基于固件、拓扑、位置信息来分配。这样做的优点是命名全自动的、可预知的...
- Linux 网卡名称enss33修改为eth0
-
一、CentOS修改/etc/sysconfig/grub文件(修改前先备份)为GRUB_CMDLINE_LINUX变量增加2个参数(net.ifnames=0biosdevname=0),修改完成...
- CentOS下双网卡绑定,实现带宽飞速
-
方式一1.新建/etc/sysconfig/network-scripts/ifcfg-bond0文件DEVICE=bond0IPADDR=191.3.60.1NETMASK=255.255.2...
- linux 双网卡双网段设置路由转发
-
背景网络情况linux双网卡:网卡A(ens3)和网卡B(...
- Linux-VMware设置网卡保持激活
-
Linux系统只有在激活网卡的状态下才能去连接网络,进行网络通讯。修改配置文件(永久激活网卡)...
- VMware虚拟机三种网络模式
-
01.VMware虚拟机三种网络模式由于linux目前很热门,越来越多的人在学习linux,但是买一台服务放家里来学习,实在是很浪费。那么如何解决这个问题?虚拟机软件是很好的选择,常用的虚拟机软件有v...
- 2023年最新版 linux克隆虚拟机 解决网卡uuid重复问题
-
问题描述1、克隆了虚拟机,两台虚拟机里面的ip以及网卡的uuid都是一样的2、ip好改,但是uuid如何改呢?解决问题1、每台主机应该保证网卡的UUID是唯一的,避免后面网络通信有问题...
- Linux网卡的Vlan配置,你可能不了解的玩法
-
如果服务器上连的交换机端口已经预先设置了TRUNK,并允许特定的VLAN可以通过,那么服务器的网卡在配置时就必须指定所属的VLAN,否则就不通了,这种情形在虚拟化部署时较常见。例如在一个办公环境中,办...
- Centos7 网卡绑定
-
1、切换到指定目录#备份网卡数据cd/etc/sysconfig/network-scriptscpifcfg-enp5s0f0ifcfg-enp5s0f0.bak...
- Linux搭建nginx+keepalived 高可用(主备+双主模式)
-
一:keepalived简介反向代理及负载均衡参考:...
- Linux下Route 路由指令使用详解
-
linuxroute命令用于显示和操作IP路由表。要实现两个不同子网之间的通信,需要一台连接两个网络的路由器,或者同时位于两个网络的网关来实现。在Linux系统中,设置路由通常是为了解决以下问题:该...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- oracle忘记用户名密码 (59)
- oracle11gr2安装教程 (55)
- mybatis调用oracle存储过程 (67)
- oracle spool的用法 (57)
- oracle asm 磁盘管理 (67)
- 前端 设计模式 (64)
- 前端面试vue (56)
- linux格式化 (55)
- linux图形界面 (62)
- linux文件压缩 (75)
- Linux设置权限 (53)
- linux服务器配置 (62)
- mysql安装linux (71)
- linux启动命令 (59)
- 查看linux磁盘 (72)
- linux用户组 (74)
- linux多线程 (70)
- linux设备驱动 (53)
- linux自启动 (59)
- linux网络命令 (55)
- linux传文件 (60)
- linux打包文件 (58)
- linux查看数据库 (61)
- linux获取ip (64)
- linux进程通信 (63)