数据库

* 多表查询 * 索引 * python 操作数据库 * mysql主从复制 * 总结

面试题 https://blog.csdn.net/liu_weiliang10405/article/details/123930244

概念

数据 data
数据库 database
数据库管理系统 DBMS
数据库管理员 DBA

数据库的分类

关系型: mysql\oracle\ sqlite\ sql server 适合我们在存取数据的时候 字段不确定的情况下
非关系型: redis\mongdb 我们总是用一个固定的字段来获取某些信息 并且对数据的存取速度要求都非常高

区别

1)mysql :关系型数据库,用于持久化的存储数据到硬盘,功能强大,但读取速度较慢

2)redis :非关系型数据库,也是缓存数据库,用于存储使用 较为频繁的数据 到缓存中,读取速度快 ,持久化是使用AOF和rdb方式,支持事务,存储小量的数据

3)mongodb: 不支持事务,支持查询的语言比较多(json,xml,bson),适合大数据量的存储

应用场景

redis:数据量较小的更性能操作和运算上
MongoDB:主要解决海量数据的访问效率问题

explain执行计划

使用explain关键字可以模拟优化器执行sql查询语句,explain主要用于分析查询语句或表结构的性能瓶颈。

1.explain的作用
通过explain+sql语句可以知道如下内容:

①表的读取顺序。(对应id)

②数据读取操作的操作类型。(对应select_type)

③哪些索引可以使用。(对应possible_keys)

④哪些索引被实际使用。(对应key)

⑤表直接的引用。(对应ref)

⑥每张表有多少行被优化器查询。(对应rows)

explain(执行计划)包含的信息十分的丰富,着重关注以下几个字段信息。

①id,select子句或表执行顺序,id相同,从上到下执行,id不同,id值越大,执行优先级越高。

②type,type主要取值及其表示sql的好坏程度(由好到差排序):system>const>eq_ref>ref>range>index>ALL。保证range,最好到ref。

③key,实际被使用的索引列。

④ref,关联的字段,常量等值查询,显示为const,如果为连接查询,显示关联的字段。

⑤Extra,额外信息,使用优先级Using index>Using filesort(九死一生)>Using temporary(十死无生)。

mysql 有哪些日志
undo 日志:用于支持事务的原子性、一致性,用于支持事务回滚以及MVCC

    redo 日志:用于支持事务的持久化

    查询日志:记录所有对数据库请求的信息。

    慢查询日志:将运行时间超过阈值的所有SQL语句都记录到慢查询的日志文件中

    二进制日志:记录对数据库执行更改的所有操作。

    中继日志:用于从机复制主机信息。

mysql删除所有重复的数据

https://blog.csdn.net/qq_37634156/article/details/125428654

mysql客户端的启动:
  1. 在cmd里执行

    mysql -uroot -p
    Enter password:
    root默认的用户 权限相对大

  2. 在mysql的客户端执行

    mysql> exit # 退出客户端

  3. 在cmd中执行的 服务端的启停:

    net start mysql
    net stop mysql

mysql 导入 导出

导出(备份)所有
导出时没有参数--databases 需要先创建数据库在source,加上--databases,直接source就行

#备份表(不需要进入到mysql)
语法:mysqldump -u root -p  数据库名 > 路劲/新名字 (注:路经后边不能有中文)
mysqldump -u root -p --all-databases > /tmp/db.sql

恢复到表数据
先进入到mysql

create database 数据库名
use 数据库
source 文件的路劲

导出db1、db2两个数据库的所有数据

mysqldump -uroot -proot --databases db1 db2 >/tmp/user.sql
mysqldump -uroot -p -B db1 db2 >/tmp/user.sql

恢复数据库

source 文件路劲

导入

Mysql -uroot -p -b 数据库名< /opt/all db.sql
或者
mysql>source /data/all.sql;

其实导出的是库里面的表,要想导入,先建一个database库,进入库里边后再source.


存储引擎

  1. Innodb:默认使用mysql5.6

特点: 支持事务\行级锁\外键

事务: 事务由单独单元的一个或者多个sql语句组成,在这个单元中,每个mysql语句时相互依赖的。而整个单独单元作为一个不可分割的整体,
n句sql是一个完整的事件,这n句sql要么一起成功,要么一起失败(转账)
事务的四个特性:
原子性(Atomicity):所有操作要么全部成功,要么全部失败回滚
一致性(Consistency):事务必须使数据库从一个一致性状态变换到另一个一致性状态
隔离性(Isolation):一个事务的执行不能让其它事务干扰
持久性(Durability):事务一旦结束,数据就持久到数据库

数据库事务可以对应哪些隔离级别
1、脏读:B事务读取到了A事务尚未提交的数据
2、不可重复读:一个事务中两次读取的数据的内容不一致
3、幻读/虚读:一个事务中两次读取的数据的数量不一致

隔离级别:
1、read uncommitted : 读未提交 :哪个问题都不能
2、read committed:读已提交 :可以解决脏读 —- oracle默认的
3、repeatable read:可重复读:可以解决脏读和不可重复读 —mysql默认的
4、serializable:串行化:可以解决脏读不可重复读和虚读—相当于锁表

mysql默认事务并发隔离级别是什么?
默认的为Repeatable read (可重复读)

行级锁: 优点: 能够支持更多的修改数据的并发操作; 缺: 修改的行数太多,效率会受影响

表级锁:
     缺点: 不支持并发的修改同一张表中的数据;
     优:不需要加很多锁,,效率高

外键: 在本表中有一个字段 关联 外表中的另一个字段

为什么要用innodb做存储引擎?
因为他是mysql5.6 以上默认使用的,考虑到程序今后的扩展,我要用支持事务的inndb,并且并发的删除和修改的效率比其他引擎高一些

  1. myisam: 默认使用mysql5.5
    特点:表级锁

3)memory: 缓存的存储方式 内存
特点:读取快,不能完成数据的持久化存储,断电数据就会消失

4)blackhole :黑洞
特点: 集群(多台mysql服务,提供高可用的时候涉及到的一种存储引擎) 多级主从复制中的一台机器上的数据库常用的存储引擎

表级锁
https://blog.csdn.net/xixihaha_coder/article/details/126407735
分三类: 1. 表锁,2. 元数据锁(meta data lock,MDL)3. 意向锁
对于表锁,分为两类:
1.表共享读锁(read lock)
2. 表独占写锁(write lock)
语法:

加锁: lock tables 表名 ...  read/write
释放锁:unlock tables / 客户端断开链接


创建表

create table 表名(
字段名1 类型[(宽度) 约束条件],
字段名2 类型[(宽度) 约束条件],
字段名3 类型[(宽度) 约束条件]
);

例:

mysql> create table staff_info (id int,name char(10),age int(3),sex enum('male', 'female'), phone char(11),job char(12));
2) 查看表结构
desc (describe) 表名;   查看表的基础信息
show create table 表名 \G;  查看表的详细信息(编码 和 存储引擎)
3)修改表结构

基础数据类型

1) 数值类型
Int 整型的长度约束,实际没效果
Float 小数: float(n,m) 这个数据总长度n,小数点后为m 如:(126,45)

2) 日期时间类型
now()

datetime : 允许为空,没有默认值,能够表示的时间范围大
timestamp :不允许为空,默认值是当前时间,能够表示的时间范围小,超出范围表示为 0000-00-00 00:00:00
如果同一个表中有两个该字段,只有第一个字段会被表示为默认当前时间

3) 字符串格式
char: 定长,存储相对浪费空间,存取速度快,不管你存储什么样的数据,他都会帮你把数据的空格在显示的时候去掉
varchar: 变长,相对节省空间,存取效率相对慢,varchar类型的最大长度通常为65535个字符
检验:

concat(ch,'+')字符串格式

例子:举例: varchar(32) 和 varchar(64)区别是啥?
影响性能
首先,varchar 大家都知道是动态长度分配,他们空间开销是一样的。

区别和联系:

对于内存的消耗是不同的。对于VARCHAR数据类型来说,硬盘上的存储空间虽然都是根据实际字符长度来分配存储空间的,也就是上面所说空间开销一样。

但是对于内存来说,则不是。其时使用固定大小的内存块来保存值。就是使用字符类型中定义的长度,即定义的64或32个字符空间。显然,这对于排序或者临时表(这些内容都需要通过内存来实现)操作会产生比较大的不利影响。

再者,MySQL对于该字段建索引时如果没有限制索引的大小,索引长度会默认采用的该字段的长度,也就是说varchar(64)建立的索引存储大小要比varchar(32)建立索引存储大小大的多,加载索引使用的内存也更多,效率会低

char和vachar 区别

通过区别我们可以知道,char类型因为其长度固定,所以存储/查找时速度快,但是长度没分配好的话浪费空间,而varchar类型长度随存储数据的长度改变,所以存储/查找时速度较char类型慢,但是不浪费空间,所以当需求高存储查找速率并且对空间资源的浪费与否不是那么看重时当采用char类型,而对于空间资源的分配要求高当采用varchar类型

4) ENUM和SET类型
enum 枚举 单选+不能选不在枚举范围里的
set 集合 多选+去重+不能选不在集合里的

create table t9 (name char(20),gender enum('female','male'))
# 多选框--程序中 勾选
create table t10 (name char(20),hobby set('抽烟','喝酒','烫头','翻车'))

**)comment 添加注释
例:

CREATE TABLE `cloud_info` (

id bigint NOT NULL AUTO_INCREMENT,
region varchar(20) DEFAULT '',
area varchar(50) DEFAULT '' COMMENT '地域',)

查看注释:

show full columns from 表名;

修改注释:

alter table a modify column regin varchar(50) comment 'diyu';
5) 表的约束

(1)Not null 非空
unique 唯一:不能重复输入非空的内容,但可以输入多个null

(2) primary key 主键:非空+唯一 一张表只能有一个主键,其他的还是维持原来的约束

6) 外键

外键(foreign key)所关联的外表中的那个字段必须是唯一的,建议关联外表的主键
创建外键

create table staff_info (s_id int,name varchar(20),dep_id int,foreign key(dep_id)             references departments(dep_id));

增加外键

语法:alter table 表名 add constraint FK_ID foreign key(你的外键字段名) REFERENCES 外表表名(对应的表的主键字段名);  //FK_ID是外键的名称
alter table book add constraint fk_id foreign key(press_id) references press(id);

删除外键

语法: ALTER TABLE 表名 DROP FOREIGN KEY 外键字段名;
7) 设置自增字段
unique auto_increment  至少是唯一的才可以
default 关键字   # 设置一个默认值

一对多 删除某个字段

方式一:删除class里某一个字段

create table class (id int,class_name char(12)); 
alter table class modify id int unique;  关联外键,字段至少唯一
create table stu (id int,stu_name char(20),class_id int,foreign key (class_id) 
references class(id));

先删除stu里所关联class的id的字段
delete from class where id =1;
才能删class里对应的字段:
delete from class id=1;

方式二:删除外键所关联的多个字段(直接删除)
加上on update cascade on delete cascade(连级删除或更新)

create table class (id int  primary key,class_name char(12)); 

关联外键,字段至少唯一

create table stu (id int  primary key,stu_name char(20),class_id int,foreign key (class_id)   references class(id) on update cascade  on delete  cascade);

多对多 外键
创建表

create table author(
id int primary key auto_increment,
name varchar(20)
);
create table book(
id int primary key auto_increment,
name varchar(20)
);

#这张表就存放作者表与书表的关系,即查询二者的关系查这表就可以了
create table author2book(
id int not null unique auto_increment,
author_id int not null,
book_id int not null,
constraint fk_author foreign key(author_id) references author(id)
on delete cascade
on update cascade,
constraint fk_book foreign key(book_id) references book(id)
on delete cascade
on update cascade,
primary key(author_id,book_id)
);

数据的增删改查

1)增加数据

insert into 表名 value (1,'alex',83,'不详');  一次插入一条数据
insert into 表名 values (1,'alex',83,'不详'),(2,'wusir',74,'male'); 支持一次写入多条数据
insert into 表名 (name,age,sex) values ('alex',83,'不详');

2) 修改数据

update 表名 set 字段名=值 where 条件
update 表名 set(修改成啥) 字段名1=值1,字段名2=值2 where 条件(在那一行)

3) 删除数据

delete from 表 where 条件;
delete from 表;  清空表
auto_increment 自增字段 至少是(int unique)

4)单表查询 select

select * from 表名; * 表示所有的内容
select 字段1,字段2 from 表;  表示查指定的列的内容
select distinct 字段名 from 表; distinct关键字表示去重
在select字段可以使用四则(加减乘除)运算
select 字段*12 from 表
select 字段 as 新字段名 from 表   给字段重命名

两个格式化函数

concat()  concat_ws()
concat('自己想拼的内容',字段,'你想拼的内容');
Select concat('姓名:',emp_name,'年薪:',salary) AS annual_salary from employee;
concat_ws(':',字段1,字段2)

Case语句

SELECT
   (
       CASE
       WHEN emp_name = 'jingliyang' THEN
           emp_name
       WHEN emp_name = 'alex' THEN
           CONCAT(emp_name,'_BIGSB')
       ELSE
           concat(emp_name, 'SB')
       END
   ) as new_name
 FROM
    employee;

where条件
对表当中的数据进行一个条件的筛选
对一个值的判断 = > < != <> >= <=
对一个范围的判断 between 小的值 and 大的值 [小的值,大的值]

select emp_name,salary from employee where salary between 10000 and 20000;

关键字IS NULL(判断某个字段是否为NULL不能用等号,需要用IS)

select emp_name,post_comment from employee where post_comment is not null;

**模糊匹配 **
like '%a_'
regext :字段名 ‘^\d{15}$’
'a'的名字
'%a'以a结尾,'a%'表示以a开头,'%a%'表示匹配中间带个a的字符串
'%'通配符 匹配任意长度的任意内容

SELECT * FROM employee 
     WHERE emp_name LIKE 'eg%';

'a' 表示任意的一个字符a,'a_'以a开头后面是任意的两个字符
'_' 匹配一个长度的任意内容

逻辑运算符
and 两个条件必须都成立 才算成立
or 只要有一个条件成立就成立
not 非

SELECT emp_name,salary FROM employee 
    WHERE salary=3000 OR salary=3500 OR salary=4000 OR salary=9000 ;

SELECT emp_name,salary FROM employee 
    WHERE salary IN (3000,3500,4000,9000) ;

SELECT emp_name,salary FROM employee 
    WHERE salary NOT IN (3000,3500,4000,9000) ;

group by 分组(带去重的功能)
1) select 数据 from 表 where 条件 group by 分组

select post from employee where depart_id > 1;

结果 是 查出来有多少个部门 就有多少条数据
2) GROUP BY关键字和GROUP_CONCAT()函数一起使用
想要拿到部门对应的所有员工的名字,用GROUP_CONCAT()函数

select post,group_concat(emp_name) from employee where depart_id<3 group by post; 结果是符合条件里的部门的所有人名字

聚合函数
count(字段) 统计有多少条记录是符合条件的 只统计字段不为空的那一行数据

count(*) # count(1)	# min  # max  # avg  # sum

order by 排序
默认是升序
降序 从大到小排 desc

SELECT * FROM employee ORDER BY salary DESC;

limit限制
limit n 取n个
limit m,n 从m +1 开始 取n条
limit n offset m 从m+1开始 取n个

**having **
对group by 分组后的结果进行过滤和筛选
能够 使用聚合函数
Having: 如果是group by 用到的关键字, select 当中用到的名字 聚合函数要用到的名字

优先级

FROM 表名
    WHERE 条件
    GROUP BY field
    HAVING 筛选
ORDER BY field
    LIMIT 限制条数

.多表查询

Select * from 表一,表二
1.连表查询:

用的是on连接
1) 内连接 (inner join) :只有两张表中条件互相匹配上的项才能被显示出来

select 字段 from 表1 inner join 表2 on 条件
select * from class inner join stu on stu.class_id = class.id;

等同于
Select * from class,stu where stu.class_id = class.id

2) 外链接
左外链接(left join):会完整的显示左表,根据条件显示右表

select 字段 from 表1 left join 表2 on 条件

右外链接(right join):会完整的显示右表,根据条件显示左表

select 字段 from 表1 right join 表2 on 条件

全外链接
用union连接

from 表1 left join 表2 on 条件 union 表1 right join 表2 on 条件
    select * from employee as emp left join department as dep on emp.dep_id = dep.id
union
    select * from employee as emp right join department as dep on emp.dep_id = dep.id;
2.子查询 (效率比连表查询低)

在一条sql中两个select,并且一个select的结果是另一个select的条件
用的是 in 连接

select * from 表1 where 字段 = (select 字段 from 表2 where 条件 = 值)
select * from 表1 where 字段 in (select 字段 from 表2 where 条件 = 值)

例子: 查询品骏年龄在25岁以上的部门

#用链表查询
select dem.name  from department as dep inner join employee as emp on emp.dep_id = dep.id group by dep_id having avg(age)>25;
#子查询
select name from department where id in (select dep_id from employee group by dep_id having avg(age)>25)

例子:查看技术部员工的名字

#连表
select emp.name from employee as emp inner join department as dep on emp.dep_id = dep.id where dep.name='技术';
#子查询
select name from employee where dep_id = (select id from department where name='技术')

索引

1.索引原理

索引的目的在于提高查询效率

有什么好处坏处:占空间,拖慢写的速度

本质都是:通过不断地缩小想要获取数据的范围来筛选出最终想要的结果,同时把随机的事件变成顺序的事件,也就是说,有了这种索引机制,我们可以总是用同一种查找方式来锁定数据
索引越多,占用磁盘空间越大,修改表时对索引 的重构和更新很麻烦

2.对哪些字段添加索引
    1、表的主键、外键必须有索引; 
    2、数据量超过300的表应该有索引; 
    3、经常与其他表进行连接的表,在连接字段上应该建立索引; 
    4、经常出现在Where子句中的字段,特别是大表的字段,应该建立索引; 
    5、索引应该建在选择性高的字段上; 
    6、索引应该建在小字段上,对于大的文本字段甚至超长字段,不要建索引; 
    7、复合索引的建立需要进行仔细分析;尽量考虑用单字段索引代替: 
    A、正确选择复合索引中的主列字段,一般是选择性较好的字段; 
    B、复合索引的几个字段是否经常同时以AND方式出现在Where子句中?单字段查询是否极少甚至没有?如果是,则可以建立复合索引;否则考虑单字段索引; 
    C、如果复合索引中包含的字段经常单独出现在Where子句中,则分解为多个单字段索引; 
    D、如果复合索引所包含的字段超过3个,那么仔细考虑其必要性,考虑减少复合的字段; 
    E、如果既有单字段索引,又有这几个字段上的复合索引,一般可以删除复合索引; 
    8、频繁进行数据操作的表,不要建立太多的索引; 
    9、删除无用的索引,避免对执行计划造成负面影响

创建索引:

Create index age on student(age)

删除索引

drop index 索引名字 on索引的表

1.b+树 以平衡树为基础的
1).所有的非叶子结点不存储真实的数据
2).所有的叶子结点之间都被添加了双向链表
数据库索引的原理,为什么要用 B+树,为什么不用二叉树?
二叉树特殊化为一个链表,相当于全表扫描。平衡二叉树相比于二叉查找树来说,查找效率更稳定,总体的查找速度也更快。
平衡二叉树可是每个节点只存储一个键值和数据的,如果是B树,可以存储更多的节点数据,树的高度也会降低,因此读取磁盘的次数就降下来啦,查询效率就快啦。
B+树非叶子节点上是不存储数据的,仅存储键值,而B树节点中不仅存储键值,也会存储数据。innodb中页的默认大小是16KB,如果不存储数据,那么就会存储更多的键值,相应的树的阶数(节点的子节点树)就会更大,树就会更矮更胖,如此一来我们查找数据进行磁盘的IO次数有会再次减少,数据查询的效率也会更快。
B+树索引的所有数据均存储在叶子节点,而且数据是按照顺序排列的,链表连着的。那么B+树使得范围查找,排序查找,分组查找以及去重查找变得异常简单。

2. innodb和myisam的索引的存储方式

innodb 内部 有一个 聚集索引(聚簇索引),非聚集索引
myisam 内部 没有聚集索引 ,所有索引都是非聚集索引

3. 索引的种类

primary key: 除了约束 非空 + 唯一之外 还有其他的作用 聚集索引
unique: 约束 唯一 非聚集索引的作用
index: 没有约束的作用 普通的非聚集索引
联合唯一索引
联合主键索引
联合索引

4. 正确使用索引

1.条件必须是已经创建了索引的列
2.如果在条件中对索引列使用了范围,并且这个范围很大,速度就很慢  >   <  !=  between and   not in
3.like条件 后面 必须是 'abc%'  ,如果 like '%abbasff'
4.确认使用的索引列的区分度 选择区分度低的列作为索引实际上并不能有加速查找的效果
5.索引列在条件中不能参与计算
6.and和or
and/or
    使用and条件的时候 mysql在优化查询的时候会有限选择区分度高的列先查询,来缩小其他条件要查询的范围
or 只会从左到右依次进行判断
 所有条件中出现的列区分度都需要很高
 对每一个字段都要添加索引

**5.联合索引(重复值比较多时用它)
联合索引是指对表上的多个列合起来做一个索引

create index 索引名 on 表名(字段1,字段2...);
create index name_email on s1(name,email);

最左前缀原则
# s1(name,email)
# sql语句中条件必须含有name这个字段**

6.覆盖索引

InnoDB存储引擎支持覆盖索引(covering index,或称索引覆盖),即从辅助索引中就可以得到查询记录,而不需要查询聚集索引中的记录。(不需要再回表查了)
例子:

s elect name from 表 where id =10000  # 用到索引了 ,但是不是覆盖索引
select id from 表 where id =10000  # 用到索引了 ,也是覆盖索引

索引不适合哪些场景
数据量少的不适合加索引
更新比较频繁的也不适合加索引
区分度低的字段不适合加索引(如性别)

mysql优化

1.数据库的优化
  读写分离
  多级的主从复制
2.数据结构的优化
  正确建立表关系 表该拆的拆
  垂直分表
  水平分表
  要使用固定长度的字段而不是变长字段
  长度越固定的字段要在建建表的时候放在左边
  适当的字段的约束
3.sql语句的优化
  使用连表查询代替子查询
  正确建立索引,不要创建没有用的索引
  正确的使用索引

分库与分表的设计
水平分库:以字段为依据,按照一定策略(hash、range等),将一个库中的数据拆分到多个库中。

水平分表:以字段为依据,按照一定策略(hash、range等),将一个表中的数据拆分到多个表中。

垂直分库:以表为依据,按照业务归属不同,将不同的表拆分到不同的库中。

垂直分表:以字段为依据,按照字段的活跃性,将表中字段拆到不同的表(主表和扩展表)中。

分库分表可能遇到的问题
事务问题:需要用分布式事务啦

跨节点Join的问题:解决这一问题可以分两次查询实现

跨节点的count,order by,group by以及聚合函数问题:分别在各个节点上得到结果后在应用程序端进行合并。

数据迁移,容量规划,扩容等问题

ID问题:数据库被切分后,不能再依赖数据库自身的主键生成机制啦,最简单可以考虑UUID

跨分片的排序分页问题(后台加大pagesize处理?)

mysql 连接数据库

1.在终端提交事务

begin;  # 开启事务
select * from emp where id = 1 for update;  # 查询id值,for update添加行锁;
update emp set salary=10000 where id = 1; # 完成更新
commit; # 提交事务

2.使用python 操作mysql数据库

import pymysql

    conn = pymysql.connect(
        host='localhost', user='root', password="root",
        database='db', port=3306, charset='utf-8', )
    cur = conn.cursor(cursor=pymysql.cursors.DictCursor)
    创建一个游标对象
    # 游标里什么都不写是元祖形式,写上.cursors.DictCursor 就是字典形式

    sql2 = 'select sname from student for update;', 添加一个锁
    cursor.execute('select * from s1  where email="eva2300@oldboy" or email="eva6666@oldboy"')
    ret = cursor.fetchmany(2)  # 取几就打印几个
    fetchall()  # 全取     
    fetchone() #只取一个
    print(ret)
    conn.commit()  # 提交到数据库
    conn.close()

简述mysql主从复制原理?

(1) master将改变记录到二进制日志(binary log)中(这些记录叫做二进制日志事件,binary log events);
(2) slave将master的binary log events拷贝到它的中继日志(relay log);
(3) slave重做中继日志中的事件,将改变反映它自己的数据。

总结:

查
  单表查
     select distinct * from 表 where 条件 group by 字段 having 过滤条件 order by 字段 limit n,m;
     聚合函数 : sum avg max min count
     分组聚合 : 求某个商品的平均价格,总销量,求部门的最高工资,求本月平均打卡时间最早的
  多表查
     多表查询
        连表查询
           inner join
           left join
           right join
        子查询
           在一条sql中两个select,并且一个select的结果是另一个select的条件
     推荐连表查询的效率高

四, mongodb与MySQL的不同有哪些
爱喝马黛茶的安东尼爱喝马黛茶的安东尼2020-01-03 11:03:12原创4175

MySQL与MongoDB都是开源的常用数据库,但是MySQL是传统的关系型数据库,MongoDB则是非关系型数据库,也叫文档型数据库,是一种NoSQL的数据库。它们各有各的优点,关键是看用在什么地方。所以我们所熟知的那些SQL语句就不适用于MongoDB了,因为SQL语句是关系型数据库的标准语言。

一、关系型数据库-MySQL

1、在不同的引擎上有不同的存储方式。

2、查询语句是使用传统的sql语句,拥有较为成熟的体系,成熟度很高。

3、开源数据库的份额在不断增加,mysql的份额页在持续增长。

4、缺点就是在海量数据处理的时候效率会显著变慢。

二、非关系型数据库-MongoDB

非关系型数据库(nosql ),属于文档型数据库。先解释一下文档的数据库,即可以存放xml、json、bson类型系那个的数据。这些数据具备自述性,呈现分层的树状数据结构。数据结构由键值(key=>value)对组成。

1、存储方式:虚拟内存+持久化。

2、查询语句:是独特的MongoDB的查询方式。

3、适合场景:事件的记录,内容管理或者博客平台等等。

4、架构特点:可以通过副本集,以及分片来实现高可用。

5、数据处理:数据是存储在硬盘上的,只不过需要经常读取的数据会被加载到内存中,将数据存储在物理内存中,从而达到高速读写。

6、成熟度与广泛度:新兴数据库,成熟度较低,Nosql数据库中最为接近关系型数据库,比较完善的DB之一,适用人群不断在增长。

三、MongoDB优势与劣势

优势:

1、在适量级的内存的MongoDB的性能是非常迅速的,它将热数据存储在物理内存中,使得热数据的读写变得十分快。

2、MongoDB的高可用和集群架构拥有十分高的扩展性。

3、在副本集中,当主库遇到问题,无法继续提供服务的时候,副本集将选举一个新的主库继续提供服务。

4、MongoDB的Bson和JSon格式的数据十分适合文档格式的存储与查询。

劣势:

1、 不支持事务操作。MongoDB本身没有自带事务机制,若需要在MongoDB中实现事务机制,需通过一个额外的表,从逻辑上自行实现事务。

2、 应用经验少,由于NoSQL兴起时间短,应用经验相比关系型数据库较少。

3、MongoDB占用空间过大。

四、对比

TOP PERCENT 实例

使用百分比作为参数
例: SQL 语句从 websites 表中选取前面百分之 50 的记录

SELECT TOP 50 PERCENT * FROM Websites;

使用 SQL [charlist] 通配符

MySQL 中使用 REGEXP 或 NOT REGEXP 运算符 (或 RLIKE 和 NOT RLIKE) 来操作正则表达式。
下面的 SQL 语句选取 name 以 "G"、"F" 或 "s" 开始的所有网站:

SELECT * FROM Websites
WHERE name REGEXP '^[GFs]';

带有文本值的 NOT BETWEEN 操作符实例

下面的 SQL 语句选取 name 不介于 'A' 和 'H' 之间字母开始的所有网站:
实例

SELECT * FROM Websites
WHERE name NOT BETWEEN 'A' AND 'H';

UNION 操作

UNION 操作符用于合并两个或多个 SELECT 语句的结果集。
请注意,UNION 内部的每个 SELECT 语句必须拥有相同数量的列。列也必须拥有相似的数据类型。同时,每个 SELECT 语句中的列的顺序必须相同。

SQL UNION 语法

SELECT column_name(s) FROM table1
UNION
SELECT column_name(s) FROM table2;

注释:默认地,UNION 操作符选取不同的值。如果允许重复的值,请使用 UNION ALL。

SQL UNION ALL 语法

SELECT column_name(s) FROM table1
UNION ALL
SELECT column_name(s) FROM table2;

注释:UNION 结果集中的列名总是等于 UNION 中第一个 SELECT 语句中的列名。

insert into select 语句

INSERT INTO SELECT 语句从一个表复制数据,然后把数据插入到一个已存在的表中。目标表中任何已存在的行都不会受影响

insert into selec 语法

我们可以从一个表中复制所有的列插入到另一个已存在的表中:

INSERT INTO table2
SELECT * FROM table1;

或者我们可以只复制希望的列插入到另一个已存在的表中:

INSERT INTO table2
(column_name(s))
SELECT column_name(s)
FROM table1;

select into from 和 insert into select from和create table as select * from 都是用来复制表

select into from不是用在sql 的
两者的主要区别为:
select into from 和 create table as select * from 要求目标表不存在,因为在插入时会自动创建;insert into select from 要求目标表存在。所以我们除了插入源表source_table的字段外,还可以插入常量,如sql语句:
1.新表不存在
复制表结构即数据到新表

create table new_table
select * from old_talbe;

这种方法会将old_table中所有的内容都拷贝过来,用这种方法需要注意,new_table中没有了old_table中的primary key,Extra,auto_increment等属性,需要自己手动加,具体参看后面的修改表即字段属性.
只复制表结构到新表

# 第一种方法,和上面类似,只是数据记录为空,即给一个false条件
create table new_table
select * from old_table where 1=2;
 
# 第二种方法
create table new_table like old_table;

2.新表存在
复制旧表数据到新表(假设两个表结构一样)

insert into new_table
select * from old_table;

复制旧表数据到新表(假设两个表结构不一样)

insert into new_table(field1,field2,.....)
select field1,field2,field3 from old_table;

复制全部数据

select * into new_table from old_table;

只复制表结构到新表

select * into new_talble from old_table where 1=2;

posted on 2020-03-05 16:58  xm微微一笑  阅读(93)  评论(0编辑  收藏  举报

导航