深入浅出SQL(6)-聪明的表设计

2023-11-19

该系列文章系个人读书笔记及总结性内容,任何组织和个人不得转载进行商业活动!

 

聪明的表设计:为什么要规范化

 

本章多是理论,请注意理解;

    我们到目前为止创建的表,都没有经过仔细考虑;随着数据的越来越多,我们需要考虑的更多,好让现在的WHERE子句简单一点;我们需要让表更正常、更规范;

 

两张鱼的表:

表一:

鱼的学名——鱼的俗名——重量——捕获地点

common          species       weight    location

草甘                草鱼            500g        查干湖,吉林

 

表二:

捕获者的姓名——鱼的俗名——重量——捕获水域——捕获地区——捕获日期

fitst_name   last_name   common  weight   location    state                date

hua              Q                 草甘        500g      查干湖        吉林              6/2/2018

 

表一缺乏捕获者的信息:

    但是一名鱼类研究者,在查找表的时候,上述4个字段才是他关注的;

 

表二的信息相对更细致:

    作为一名杂志撰稿人,了解鱼的这些信息还是很有必要的;

 

对于上述两张表针对吉林捕捞的鱼的记录编写SQL:

    SELECT * FROM biao1 WHERE location LIKE '%吉林';

    SELECT * FROM biao2 WHERE state = '吉林’;

 

我们看到:

对于表一:我们必须使用LIKE关键字取得查询结果;

对于表二:我们直接通过一个地区字段作为查询条件;

 

两种方式对于不同的使用表的人,都可以满足各自的需求,但是:

    如果你的表中包含复杂信息的话,LIKE搜索精确数据的能力就显得不足了;

    查询越简单越好;

 

是不是可以使用多个列存储地址呢,一列存储详细的地址,一列存储简单的地址:

    这看似是个不错的方法,但是有两个问题:

    首先,这回占用更多的空间;

    其次,由于两列的数据有重叠的地方,这代表每次修改数据的时候都要在UPDATE语句中多加一个子句;

 

使用数据的方式 和 表的设计方式 是相互影响的;

    良好的表结构设计可以让数据的处理方式更简单;

 

SQL是一种用于关系数据库的语言,那‘关系’是什么?

 

表都是基于关系的:

    SQL因关系数据库管理系统RDBMS而出名;

    对于设计表的人而言,就是要设计一个杀手级的表,必须考虑列彼此之间的关系,多个列是如何一起描述某项事物的;

 

难点在于使用列描述事物,好让取得数据更加方便;

设计方向取决于我们对表的需求;

 

创建表步骤:

1.挑出事物,挑出你希望表描述的某样事物;

2.列出一份关于那样事物的信息列表,这些信息都是使用表时的必要信息;    

    如何使用这张表;

3.使用信息列表,把关于那样事物的综合信息拆分成小块信息,以便用于组织表;

    轻松查询这张表;

 

这里的疑问:

    鱼类研究者的需求:通过查找鱼的学名或俗名得知雨的重量和地点;

    杂志撰稿人的需求:通说俗名,得知捕获者的姓名、重量、捕获水域、捕获地区、捕获日期;

 

对于不同的使用者来讲,上述的表设计都有各自的合理性;

    我们把‘关于那样事物的综合信息拆分成小块信息’的细致程度,用原子性来描述;

    个人认为,关于数据原子性的界定,取决于我们实际的需求;

    

原子性数据:

    原子(atom)是一块无法或不应该分割的信息;

    对于数据而言,数据的原子性,就表示它已经被分割为最小块;已经不能或不应该再被分割;

 

比如对一个送货员来说,一列存储街道名门牌号的列就已经具有了原子性;如果将数据拆分成街道名称+门牌号两列,查询反而会更长;

 

原子性和你的表:

如何理解表中内容:

1.表在描述什么事物;

2.以何种方式使用表能更好取得描述的事物;

3.列是否包含原子性数据,让查询更简短准确;

 

让数据具有原子性:

    并不是将数据尽可能的分割的非常小,而是要分割成创建有效率的表所需的最小片段

    别把数据切割的超出必要;如果不需要额外增加列,就别因为可以增加而增加;

    原子性有助于确保表内容的准确性,也能使查询更有效率,因为查询会因原子性而更容易设计;

 

原子性数据的正式规则:

规则一:

    具有原子性数据的列中不会有多个类型相同的值;

    比如,喜欢的运动字段sport下,值为足球、篮球……    

    保持数据的简洁性,否则如果查询具体某个兴趣将是一场噩梦;

first_name——last_name——intrests

hua                    Q                    football,backetball

 

规则二:

    具有原子性数据的表中不会有多个存储同类数据的列;

    列的划分不应该有涵义上的交叉;

teacher——student1——student2——student3

Yuan            hua1            hua2                hua3

 

规范化的原因:

    让表规范化(normalization)表示表遵循某些标准,即使是刚接触的新设计师也能理解;

 

让数据具有原子性是创建一个规范化表的第一步;

 

规范化表的优点:

1.规范化表中没有重复的数据,可以减少数据库的大小;

2.因为查找的数据较少,你的查询会更为快捷;

 

达成1NF的半路上:

    具有原子性的数据只让我们的表现规范了一半;

    完全的规范化表示我们处于第一范式(First Normal Form)的状态,简称1NF;

 

1NF:

1)每行数据行必须包含具有原子性的值;

2)每个数据行必须有独一无二的识别项,称为“主键”(Primary Key);

 

所以要让表完整的规范,需要为每条记录加上主键;

 

主键规则:

    成为主键的列必须在创建表的时候一并设置;

    

我们先来看看主键是什么;

    主键是表中的某个列,他可以让每一条记录成为唯一的;

    主键用于独一无二地识别出每条记录;

    即,主键中的数据不能重复;

 

比如对于个人信息,可以使用身份证号进行标示,但是你可以保证数据库绝对安全吗?否则如果数据被偷走,你的客户资料也就一并曝光了;

 

主键的特征:

1)主键不可以为NULL;因为NULL值不唯一

2)插入新纪录时必须指定主键值;否则主键就有可能是NULL;

3)主键必须简洁;只是一个独一无二的数据,不该有其他内容;

4)主键值不可以被修改;意外的输入值可能破坏主键的唯一性;

 

最佳主键可能是新的主键:

    最佳方式是另外创建一个包含唯一性主键的列;可以称之为ID;

 

如下表结构:

id——last_name——first_name

1        hua                    Q1

2        hua                    Q2

 

ID列让表中记录具有了唯一性;这张表也因此处于第一范式的状态;

 

人造(synthetic)主键:使用虚构的ID列作为主键;

自然(natural)主键:使用人的身份证信息作为主键;

 

我们后续会继续讨论:

    第二范式、第三范式,每一级范式都会增加更严格、更精确的规则;

    在表设计的过程中,有些字段可能没有原子性,是因为我们并不需要那样做,比如使用关键词进行评论,评论字段中的数据无原子性,但是它也并不需要原子化;

 

朝规范化前进:

    让数据具有原子性;

    加上主键:主键的创建通常会在编写CREATE TABLE时进行;

 

既然这样,我们是不是可以这样修改我们之前不完美的表:

1)查出所有数据;

2)创建一张规范化的表;

3)把旧数据INSERT INTO到新表,并改变每一行以符合新表的结构;

4)DROP TABLE掉就表;

 

但是,已经装满数据的表,我们并不希望DROP TABLE之后,再重新输入所有数据……

 

所以,我们需要对一张不具原子性,没有主键的表进行更新,我们介绍一个新的命令:

但在修理已有表的方式前,我们来看看如何重新设计一张更加标准的表;

 

我们设计的CREATE TABLE:

    我们回顾下第一章创建的表my_contacts:

profession、location和seeking这些列能不能设计的更加具有原子性呢?

同时我们也发现,这张表没有主键;

 

我们来看下表结构:

mysql> DESC my_contacts;

+------------+--------------+------+-----+---------+-------+

| Field      | Type         | Null | Key | Default | Extra |

+------------+--------------+------+-----+---------+-------+

| last_name  | varchar(30)  | YES  |     | NULL    |       |

| first_name | varchar(20)  | YES  |     | NULL    |       |

| emal       | varchar(50)  | YES  |     | NULL    |       |

| gender     | char(1)      | YES  |     | NULL    |       |

| birthdy    | date         | YES  |     | NULL    |       |

| profession | varchar(50)  | YES  |     | NULL    |       |

| location   | varchar(20)  | YES  |     | NULL    |       |

| status     | varchar(100) | YES  |     | NULL    |       |

| seeking    | varchar(100) | YES  |     | NULL    |       |

+------------+--------------+------+-----+---------+-------+

9 rows in set (0.03 sec)

设置表时所用的SQL:

    我们想看的不是表中的字段,而是想看CREATE的代码,这样才能知道表一开始是如何设计的;

    使用命令SHOW CREATE TABLE table; 将返回可以重建表但没有数据的CREATE TABLE语句;

    这样一来,就可以随时查看表的创建方式;

mysql> SHOW CREATE TABLE my_contacts;

+-------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

| Table       | Create Table                                                                                                                                                                                                                                                                                                                                                                                                                                    |

+-------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

| my_contacts | CREATE TABLE `my_contacts` (

  `last_name` varchar(30) DEFAULT NULL,

  `first_name` varchar(20) DEFAULT NULL,

  `emal` varchar(50) DEFAULT NULL,

  `gender` char(1) DEFAULT NULL,

  `birthdy` date DEFAULT NULL,

  `profession` varchar(50) DEFAULT NULL,

  `location` varchar(20) DEFAULT NULL,

  `status` varchar(100) DEFAULT NULL,

  `seeking` varchar(100) DEFAULT NULL

) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci |

+-------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

1 row in set (0.00 sec)

可以看到:

    列名和表明前后的反撇号会在运行该命令的时候出现;(有关反撇号的作用我们一会会有说明)

    除非我们指定,否则数据列都会假设所有数据的默认值都是NULL;

    结束括号之后的文字,说明了数据如何存储,以及使用的字符集(现在是默认即可);

 

我们要基于之前的创建表的命令,创建一张规范化的新表:

    除非已经删除了旧表,否则我们需要一个新的表名;

    只靠复制粘贴是不够的,我们还需要做更多的事;

 

加上主键的CREATE TABLE:

    删除反撇号和最后一行;

    添加contact_id列并设置为NOT NULL;

    在列列表的最下方添加一行PRIMARY KEY,把新添加的contact_id设定为主键;(不为NULL,独一无二)

    设置主键的语法:PRIMARY KEY(contact_id),即把主键列的名称放在括号中;

 

我们新建一张表:flower_contacts

mysql> CREATE TABLE flower_contacts (

    ->     contact_id INT NOT NULL,

    ->     last_name varchar(30) DEFAULT NULL,

    ->     first_name varchar(20) DEFAULT NULL,

    ->     emal varchar(50) DEFAULT NULL,

    ->     gender char(1) DEFAULT NULL,

    ->     birthdy date DEFAULT NULL,

    ->     profession varchar(50) DEFAULT NULL,

    ->     location varchar(20) DEFAULT NULL,

    ->     status varchar(100) DEFAULT NULL,

    ->     seeking varchar(100) DEFAULT NULL,

    ->     PRIMARY KEY (contact_id)

    -> );

Query OK, 0 rows affected (0.11 sec)

相应的:

mysql> DESC flower_contacts;

+------------+--------------+------+-----+---------+-------+

| Field      | Type         | Null | Key | Default | Extra |

+------------+--------------+------+-----+---------+-------+

| contact_id | int(11)      | NO   | PRI | NULL    |       |

| last_name  | varchar(30)  | YES  |     | NULL    |       |

| first_name | varchar(20)  | YES  |     | NULL    |       |

| emal       | varchar(50)  | YES  |     | NULL    |       |

| gender     | char(1)      | YES  |     | NULL    |       |

| birthdy    | date         | YES  |     | NULL    |       |

| profession | varchar(50)  | YES  |     | NULL    |       |

| location   | varchar(20)  | YES  |     | NULL    |       |

| status     | varchar(100) | YES  |     | NULL    |       |

| seeking    | varchar(100) | YES  |     | NULL    |       |

+------------+--------------+------+-----+---------+-------+

10 rows in set (0.00 sec)

这里没有蠢问题:

1.我们已经知道每次插入新纪录都必须为主键列赋新值,有没有更好的办法:

    有两种方式;一种是直接利用原来就有唯一性的数据作为主键;这种可能不太容易实现;

    比较简单的一种是使用全新的主键列,用它来存储独一无二的值;

    每当使用主键时,我们可以要求SQL软件自动为主键填入新的值;

2.SHOW命令的使用场景:

    显示表中列及其数据类型:SHOW COLUMNS FROM table;

    提供重建数据库的语句:SHOW CREATE DATABASE database;        

    显示任何编了索引的列以及索引类型:SHOW INDEX FROM table;

    目前为止,我们唯一看到的索引就是主键;

    还有一个很有用的命令:SHOW WARNINGS;

        如果你从控制台收到SQL命令造成的错误信息,键入这个命令就可取得确切的警告内容;

3.反撇号的作用:

    反撇号的存在是因为RDBMS有时无法分辨列名;

    如果在列名前后加上该字符就能以SQL保留字作为列名;`select`就是一个有效的列名;

4.用保留字作为列名的问题:

    这是一个很糟糕的主意,这回让你的查询很混乱,也会引入每次都输入反撇号的麻烦;

    而且select也不是一个好列名,无法说明该列包含的数据;

 

1、2、3……自动递增“关键字AUTO_INCREMENT

    为contact_id列加上关键字AUTO_INCREMENT,就可以让SQL软件自动为该列填入数据,第一行填入1,后续递增;

    有些RDBMS类似功能的关键字可能是INDEX;

 

我们看下文档对该AUTO_INCREMENT的说明:

mysql> help auto_increment

Name: 'AUTO_INCREMENT'

Description:

The AUTO_INCREMENT attribute can be used to generate a unique identity

for new rows:

URL: http://dev.mysql.com/doc/refman/8.0/en/example-auto-increment.html

Examples:

CREATE TABLE animals (

     id MEDIUMINT NOT NULL AUTO_INCREMENT,

     name CHAR(30) NOT NULL,

     PRIMARY KEY (id)

);

INSERT INTO animals (name) VALUES

    ('dog'),('cat'),('penguin'),

    ('lax'),('whale'),('ostrich');

SELECT * FROM animals;

我们运行了这个示例:

mysql> SELECT * FROM animals;

+----+---------+

| id | name    |

+----+---------+

|  1 | dog     |

|  2 | cat     |

|  3 | penguin |

|  4 | lax     |

|  5 | whale   |

|  6 | ostrich |

+----+---------+

6 rows in set (0.00 sec)

现在,我们修改创建flower_contacts表的SQL:

DROP TABLE flower_contacts;

CREATE TABLE flower_contacts (

    contact_id INT NOT NULL AUTO_INCREMENT,

    last_name varchar(30) DEFAULT NULL,

    first_name varchar(20) DEFAULT NULL,

    emal varchar(50) DEFAULT NULL,

    gender char(1) DEFAULT NULL,

    birthdy date DEFAULT NULL,

    profession varchar(50) DEFAULT NULL,

    location varchar(20) DEFAULT NULL,

    status varchar(100) DEFAULT NULL,

    seeking varchar(100) DEFAULT NULL,

    PRIMARY KEY (contact_id)

);

现在的表是这样的:

mysql> DESC flower_contacts;

+------------+--------------+------+-----+---------+----------------+

| Field      | Type         | Null | Key | Default | Extra          |

+------------+--------------+------+-----+---------+----------------+

| contact_id | int(11)      | NO   | PRI | NULL    | auto_increment |

| last_name  | varchar(30)  | YES  |     | NULL    |                |

| first_name | varchar(20)  | YES  |     | NULL    |                |

| emal       | varchar(50)  | YES  |     | NULL    |                |

| gender     | char(1)      | YES  |     | NULL    |                |

| birthdy    | date         | YES  |     | NULL    |                |

| profession | varchar(50)  | YES  |     | NULL    |                |

| location   | varchar(20)  | YES  |     | NULL    |                |

| status     | varchar(100) | YES  |     | NULL    |                |

| seeking    | varchar(100) | YES  |     | NULL    |                |

+------------+--------------+------+-----+---------+----------------+

10 rows in set (0.00 sec)

我们尝试操作这张表,来看下AUTO_INCREMENT是如何运作的;

我们先来看几条SQL:

INSERT INTO flower_contacts

(last_name,seeking)

VALUES

('hua1','working,girlfriend'),

('hua2','working,girlfriend'),

('hua3','working,girlfriend’);



INSERT INTO flower_contacts

(contact_id,last_name,seeking)

VALUES

(5,'hua4','working,girlfriend'),

(7,'hua5','working,girlfriend');



INSERT INTO flower_contacts

(last_name,seeking)

VALUES

('hua6','working,girlfriend'),

('hua7','working,girlfriend'),

('hua8','working,girlfriend’);



INSERT INTO flower_contacts

(contact_id,last_name,seeking)

VALUES

(10,'hua9','working,girlfriend');



INSERT INTO flower_contacts

(contact_id,last_name,seeking)

VALUES

(NULL,'hua10','working,girlfriend');



DELETE FROM flower_contacts WHERE contact_id = 11;



INSERT INTO flower_contacts

(contact_id,last_name,seeking)

VALUES

(NULL,'hua10','working,girlfriend');



SELECT contact_id,last_name,seeking FROM flower_contacts;

最终查看表flower_contacts的内容如下:

mysql> SELECT contact_id,last_name,seeking FROM flower_contacts;

+------------+-----------+--------------------+

| contact_id | last_name | seeking            |

+------------+-----------+--------------------+

|          1 | hua1      | working,girlfriend |

|          2 | hua2      | working,girlfriend |

|          3 | hua3      | working,girlfriend |

|          5 | hua4      | working,girlfriend |

|          7 | hua5      | working,girlfriend |

|          8 | hua6      | working,girlfriend |

|          9 | hua7      | working,girlfriend |

|         10 | hua8      | working,girlfriend |

|         12 | hua10     | working,girlfriend |

+------------+-----------+--------------------+

9 rows in set (0.00 sec)

分析:

hua1、2、3 我们是按照文档例子的方式插入的,运行正常;

hua4、5两条则是我们指定的contact_id进行的插入,运行正常:

hua6、7、8虽然也正常插入了,但是我们看到,自增的数值是基于当前最后一条主键的值进行的自增,也就是7之后的8;

hua9的插入我们再一次指定了contact_id为10,但这一次失败了:

mysql> INSERT INTO flower_contacts 

    -> (contact_id,last_name,seeking)

    -> VALUES

    -> (10,'hua6','working,girlfriend');

ERROR 1062 (23000): Duplicate entry '10' for key 'PRIMARY'

mysql> SHOW WARNINGS;

+-------+------+----------------------------------------+

| Level | Code | Message                                |

+-------+------+----------------------------------------+

| Error | 1062 | Duplicate entry '10' for key 'PRIMARY' |

+-------+------+----------------------------------------+

1 row in set (0.00 sec)

因为我们插入的主键10重复了;

 

hua10的插入很有意思,之所以成功,是因为AUTO_INCREMENT会忽略NULL;(没有它的话就报错了)

    很明显hua10的contact_id=11;

紧接着,我们删除了contact_id = 11的这条记录,我们继续将hua10这条记录插入,此时hua10的contact_id则是基于11的增加,值为12,虽然11这条记录已经删除了;

 

可以得出的结论是:

    自增的数值是基于当前最后一条主键的值进行的自增,即便他已经被删除了;

    只要插入过的记录就会引起主键的AUTO_INCREMENT;

 

当然,contact_id=11,我们还可以继续使用:

INSERT INTO flower_contacts

(contact_id,last_name,seeking)

VALUES

(11,'hua10','working,girlfriend');

最终,表的内容如下:

mysql> SELECT contact_id,last_name,seeking FROM flower_contacts;

+------------+-----------+--------------------+

| contact_id | last_name | seeking            |

+------------+-----------+--------------------+

|          1 | hua1      | working,girlfriend |

|          2 | hua2      | working,girlfriend |

|          3 | hua3      | working,girlfriend |

|          5 | hua4      | working,girlfriend |

|          7 | hua5      | working,girlfriend |

|          8 | hua6      | working,girlfriend |

|          9 | hua7      | working,girlfriend |

|         10 | hua8      | working,girlfriend |

|         11 | hua10     | working,girlfriend |

|         12 | hua10     | working,girlfriend |

+------------+-----------+--------------------+

10 rows in set (0.00 sec)

当然,这是我们重新,开始建表实现了规范化的设计;现在我们要针对my_cotacts表,介绍我们的新命令了;

 

ALTER语句:

    改用ALERT语句,我们不用再重新开始了;(注意!!!!!不是alert,而是alter)

    带有数据的表不应该经历被丢弃、卸除、重建的步骤;我们需要的是改变现有的表;

    ALTER还会在下一章进一步介绍,我们先看看他的用法;

   

首先请回看一下前边提到的my_contacts表及其内容;

 

为现有的表添加主键:

    ALTER TABLE 并添加PRIMARY KEY;

ALTER TABLE my_contacts

ADD COLUMN contact_id INT NOT NULL AUTO_INCREMENT FIRST,

ADD PRIMARY KEY (contact_id);

 

FIRST:

    是要求软件吧新列放在最前面,这是一个可选的关键字;

    把主键放在最前面是一个很好的习惯;

 

ADD COLUMN:

    添加一个新列;

 

我们看到,有4条记录添加了新列;同时我们也看到,主键的值已经全部都填上了;

 

总结:

ATOMIC DATA:数据原子性,列中数据已拆成查询所需的最小单位;

ATOMIC DATA规则一:

    具有原子性表示在同一列中不会存在多个类型相同的数据;

ATOMIC DATA规则二:

    具有原子性表示不会用多个列来存储类型相同的数据;

SHOW CREATE TABLE:呈现创建现有表的正确语法;

PRIMARY KEY:主键,一个或一组能识别出唯一数据行的列;

FIRST NORMAL FORM(1NF):

    第一范式,每个数据行均需包含原子性数据值,而且每个数据行均需有唯一的识别方法;

AUTO_INCREMENT:

    列声明时若使用该关键字,则每次执行INSERT命令插入数据时,都会自动给列赋予唯一的递增整数值;

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

深入浅出SQL(6)-聪明的表设计 的相关文章

随机推荐

  • 【赠书活动|第六期《强化学习:原理与Python实战》】

    文章目录 RLHF是什么 RLHF适用于哪些任务 RLHF和其他构建奖励模型的方法相比有何优劣 什么样的人类反馈才是好的反馈 RLHF算法有哪些类别 各有什么优缺点 RLHF采用人类反馈会带来哪些局限 如何降低人类反馈带来的负面影响 图书简
  • 打卡C语言学习第十三天

    对之前所学内容复习和补充 练习函数书写
  • ruoyi登录流程

    首先加载登录界面会发送验证码请求和获取Cookie 会调用created函数 Getcode是获取验证码 GetCookie是获取cookie GetCodeImg函数会调用ajax发送请求给后端 后端GetMapping接口接收到请求后执
  • 搜狐2012.9.15校园招聘会笔试题

    一 不定项选择题 1 以下程序的打印结果是 include
  • Android SurfaceView

    下面就贴上一个小程序代码 主要运用SurfaceView来实现在屏幕上画一个圆 你可以通过按方向键和触摸屏幕来改变圆的位置 代码 Activity java view plain copy print package com view im
  • TypeError: 'function' object is not subscriptable

    报错 function object is not subscriptable 原因是Hi是个匿名函数 应该用 而不是 改成 即可 像这种问题TypeError function object is not subscriptable 一般
  • 迷宫问题java老鼠走迷宫(回溯法,递归,二维数组)(超级容易理解)

    回溯法迷宫问题 思路 利用回溯法和递归思想解决 findWay 方法就是专门来找出迷宫的路径 如果找到 就返回 true 否则返回 false map 就是二维数组 即表示迷宫 i j 就是老鼠的位置 初始化的位置为 1 1 因为我们是递归
  • mysql索引实现

    目前大部分数据库系统及文件系统都采用B Tree B树 或其变种B Tree B 树 作为索引结构 B Tree是数据库系统实现索引的首选数据结构 在MySQL中 索引属于存储引擎级别的概念 不同存储引擎对索引的实现方式是不同的 本文主要讨
  • Ubuntu下无法看到共享文件夹的解决办法

    1 输入以下指令 确定共享文件夹是否设置成功 vmware hgfsclient 若是设置成功 会输出贡献文件夹的名字 2 如果已经设置了共享文件夹 请输入下列指令 如果之前没有命令包则先执行sudo apt get install ope
  • 在linux下如何查看局域网的所有主机的ip地址

    策略 用nmap对局域网扫描一遍 然后查看arp缓存表就可以知道局域内ip对应的mac了 nmap比较强大也可以直接扫描mac地址和端口 执行扫描之后就可以 cat proc net arp查看arp缓存表了 或者使用命令arp a 参考
  • 【Goland】巧妙用批量替换Replace

    今天想提一嘴 IDE 的一个功能 就是批量替换 Replace in Path 大家可以按快键键 commnd 进入 Preference 然后搜索 Keymap 也就是快键键 然后搜索 Replace 找到批量替换的快键键 因为快键键就是
  • C# 处理异常

    using System using System Collections Generic using System Linq using System Text namespace Ch13CardLib public class Car
  • YAML 文件语法学习

    一 概述 YAML是一个类似 XML JSON 的标记性语言 YAML 强调以数据为中心 并不是以标识语言为重点 YAML 是一种较为人性化的数据序列化语言 可以配合目前大多数编程语言使用 YAML 的语法比较简洁直观 特点是使用空格来表达
  • 解决打印org.apache.http.wire,org.apache.http.headers日志的问题

    最近在调试接口的过程中 发现使用httpClient的时候 控制台输出了很多org apache http wire org apache http headers相关的日志 不便于我观察自己调试业务过程中输出的日志 内容如下 10 02
  • 如何把一张照片用PS做成漫画风格

    如何把一张照片用PS做成漫画风格 原素材 漫画天空 1 打开ps 打开素材 然后按住ctrl j 复制一个图层 并修改好名字 如下图操作 2 执行 滤镜 滤镜库 干画笔 如图所示 三个参数分别是 0 10 2 3 执行 滤镜 Camera
  • Box2D C++ 教程-查询 World

    声明 本文翻译自Box2D C tutorial World querying 仅供学习参考 查询World 通常你可能想知道在给定的场景中都有哪些实体 例如有一个炸弹爆炸了 周围的所有实物都会受到不同程度的破坏 那么在RTS 译者注 Re
  • java计算机毕业设计景区在线购票系统源码+mysql数据库+系统+lw文档+部署

    java计算机毕业设计景区在线购票系统源码 mysql数据库 系统 lw文档 部署 java计算机毕业设计景区在线购票系统源码 mysql数据库 系统 lw文档 部署 本源码技术栈 项目架构 B S架构 开发语言 Java语言 开发软件 i
  • 【转】结构体中Char a[0]用法——柔性数组

    有如下定义 typedef struct char a char b 0 其中元素Char b 0 叫做柔性数组 主要用于使结构体包含可变长字段 详细内容如下 柔性数组 柔性数组结构成员 C99中 结构中的最后一个元素允许是未知大小的数组
  • css hover 控制其他元素_CSS学习小结

    css语法 Selector Dcclaration Selector Property Value CSS注释 注释 CSS Selector 选择器 id class id id class class 插入样式表 外部样式表 内部样式
  • 深入浅出SQL(6)-聪明的表设计

    该系列文章系个人读书笔记及总结性内容 任何组织和个人不得转载进行商业活动 聪明的表设计 为什么要规范化 本章多是理论 请注意理解 我们到目前为止创建的表 都没有经过仔细考虑 随着数据的越来越多 我们需要考虑的更多 好让现在的WHERE子句简