1.mysql数据库存储的原理
储存过程是一个可编程的函数,它在数据库中创建并保存。它可以有SQL语句和一些特殊的控制结构组成。当希望在不同的应用程序或平台上执行相同的函数,或者封装特定功能时,存储过程是非常有用的。数据库中的存储过程可以看做是对编程中面向对象方法的模拟。它允许控制数据的访问方式。
存储过程通常有以下优点:
- a、存储过程能实现较快的执行速度。
- b、存储过程允许标准组件是编程。
- c、存储过程可以用流程控制语句编写,有很强的灵活性,可以完成复杂的判断和较复杂的运算。
- d、存储过程可被作为一种安全机制来充分利用。
- e、存储过程能够减少网络流量。
2.MySQL数据库事务的特性?
(1)原子性(Atomicity)
事务中的全部操作在数据库中是不可分割的,要么全部完成,要么均不执行。
(2)一致性(Consistency)
几个并行执行的事务,其执行结果必须与按某一顺序串行执行的结果相一致。
(3)隔离性(Isolation)
事务的执行不受其他事务的干扰,事务执行的中间结果对其他事务必须是透明的。
(4)持久性(Durability)
对于任意已提交事务,系统必须保证该事务对数据库的改变不被丢失,即使数据库出现故障
3.使用Mysql数据库中的事务的方法
MYSQL 事务处理主要有两种方法:
1、用 BEGIN, ROLLBACK, COMMIT来实现
- BEGIN 开始一个事务
- ROLLBACK 事务回滚
- COMMIT 事务确认
2、直接用 SET 来改变 MySQL 的自动提交模式:
- SET AUTOCOMMIT=0 禁止自动提交
- SET AUTOCOMMIT=1 开启自动提交
4.数据库索引
数据库索引,是数据库管理系统中一个排序的数据结构,以协助快速查询、更新数据库表中数据。索引的实现通常使用B_TREE。B_TREE索引加速了数据访问,因为存储引擎不会再去扫描整张表得到需要的数据;相反,它从根节点开始,根节点保存了子节点的指针,存储引擎会根据指针快速寻找数据。
5.索引怎么建立?原理是什么?
在表格上面创建某个一个唯一的索引。唯一的索引意味着两个行不能拥有相同的索引值。
CREATE UNIQUE INDEX 索引名称 ON 表名称 (列名称)
“列名称”规定你需要索引的列
原理:索引问题就是一个查找问题。
数据库索引,是数据库管理系统中一个排序的数据结构,以协助快速查询、更新数据库表中数据。索引的实现通常使用B树及其变种B+树。 在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构上实现高级查找算法。这种数据结构,就是索引。
6.在关系型数据库中,索引(index)存在的意义是什么?
(1)通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。
(2)可以大大加快数据的检索速度,这也是创建索引的最主要的原因。
(3)可以加速表和表之间的连接,特别是在实现数据的参考完整性方面特别有意义。
(4)在使用分组和排序子句进行数据检索时,同样可以显著减少查询中分组和排序的时间。
(5)通过使用索引,可以在查询的过程中,使用优化隐藏器,提高系统的性能。
7.redis和 mysql的区别
- readis 是内存数据库,数据保存在内存中, 速度快。
- mysql 是关系型数据库,持久化存储,存放在磁盘里面,功能强大。检索的话,会涉及到一定的 IO, 数据访问也就慢。
8.BTree索引和Hash索引的优缺点各是什么?
(1)BTree
(多路搜索树,并不是二叉的)是一种常见的数据结构。使用BTree结构可以显著减少定位记录时所经历的中间过程,从而加快存取速度。这个数据结构一般用于数据库的索引,综合效率较高。
不适合:
单列索引的列不能包含null的记录,复合索引的各个列不能包含同时为null的记录,否则会全表扫描; 不适合键值较少的列(重复数据较多的列);前导模糊查询不能利用索引(like '%XX'或者like '%XX%')
(2)Hash散列索引
Hash散列索引是根据HASH算法来构建的索引。虽然 Hash 索引效率高,但是 Hash 索引本身由于其特殊性也带来了很多限制和弊端,主要有以下这些。
适合:精确查找非常快(包括= <> 和in),其检索效率非常高,索引的检索可以一次定位,不像BTree 索引需要从根节点到枝节点,所以 Hash 索引的查询效率要远高于 B-Tree 索引。
不适合:
1、不适合模糊查询和范围查询(包括like,>,<,between……and等),由于 Hash 索引比较的是进行 Hash 运算之后的 Hash 值,所以它只能用于等值的过滤,不能用于基于范围的过滤,因为经过相应的 Hash 算法处理之后的 Hash 值的大小关系,并不能保证和Hash运算前完全一样;
2、不适合排序,数据库无法利用索引的数据来提升排序性能,同样是因为Hash值的大小不确定;
3.复合索引不能利用部分索引字段查询,Hash 索引在计算 Hash 值的时候是组合索引键合并后再一起计算 Hash 值,而不是单独计算 Hash 值,所以通过组合索引的前面一个或几个索引键进行查询的时候,Hash 索引也无法被利用。
4.同样不适合键值较少的列(重复值较多的列);
9.你用的mysql是哪个引擎,各引擎之间有什么区别?
主要 MyISAM 与 InnoDB 两个引擎,其主要区别如下:
- InnoDB 支持事务,MyISAM 不支持,这一点是非常之重要。事务是一种高级的处理方式,如在一些列增删改中只要哪个出错还可以回滚还原,而 MyISAM就不可以了;
- MyISAM 适合查询以及插入为主的应用,InnoDB 适合频繁修改以及涉及到安全性较高的应用;
- InnoDB 支持外键,MyISAM 不支持;
- MyISAM 是默认引擎,InnoDB 需要指定;
- InnoDB 不支持 FULLTEXT 类型的索引;
- InnoDB 中不保存表的行数,如 select count(*) from table 时,InnoDB需要扫描一遍整个表来计算有多少行,但是 MyISAM 只要简单的读出保存好的行数即可。注意的是,当 count(*)语句包含 where 条件时 MyISAM 也需要扫描整个表;
- 对于自增长的字段,InnoDB 中必须包含只有该字段的索引,但是在 MyISAM表中可以和其他字段一起建立联合索引;
- 清空整个表时,InnoDB 是一行一行的删除,效率非常慢。MyISAM 则会重建表;
- InnoDB 支持行锁(某些情况下还是锁整表,如 update table set a=1 where user like '%lee%'
10.Redis和MongoDB的优缺点
MongoDB 和 Redis 都是 NoSQL, 采用结构型数据存储。 二者在使用场景中, 存在一定的区别, 这也主要由于二者在内存映射的处理过程, 持久化的处理方法不同。
MongoDB 建议集群部署, 更多的考虑到集群方案,Redis 更偏重于进程顺序写入,虽然支持集群, 也仅限于主-从模式.
Redis优点
- 读写性能优异
- 支持数据持久化, 支持 AOF 和 RDB 两种持久化方式
- 支持主从复制, 主机会自动将数据同步到从机, 可以进行读写分离。
- 数据结构丰富: 除了支持 string 类型的 value 外还支持string、 hash、 set、 sortedset、 list 等数据结构。
Redis缺点
- Redis 不具备自动容错和恢复功能, 主机从机的宕机都会导致前端部分读写请求失败,需要等待机器重启或者手动切换前端的 IP才能恢复。
- 主机宕机, 宕机前有部分数据未能及时同步到从机, 切换 IP后还会引入数据不一致的问题, 降低了系统的可用性。
- Redis 的主从复制采用全量复制, 复制过程中主机会 fork 出一个子进程对内存做一份快照, 并将子进程的内存快照保存为文件发送给从机, 这一过程需要确保主机有足够多的空余内存。若快照文件较大, 对集群的服务能力会产生较大的影响, 而且复制过程是在从机新加入集群或者从机和主机网络断开重连时都会进行, 也就是网络波动都会造成主机和从机间的一次全量的数据复制,这对实际的系统运营造成了不小的麻烦。
- Redis 较难支持在线扩容, 在集群容量达到上限时在线扩容会变得很复杂。 为避免这一问题,运维人员在系统上线时必须确保有足够的空间, 这对资源造成了很大的浪费。
MongoDB优点
- 弱一致性(最终一致) , 更能保证用户的访问速度文档结构的存储方式, 能够更便捷的获取数内置 GridFS,高效存储二进制大对象 (比如照片和视频)
- 支持复制集、 主备、 互为主备、 自动分片等特性
- 动态查询
- 全索引支持,扩展到内部对象和内嵌数组
MongoDB缺点
- 不支持事务
- MongoDB 占用空间过大
- 维护工具不够成熟
11.数据库优化方案
(1)优化索引、SQL 语句、分析慢查询
(2)设计表的时候严格根据数据库的设计范式来设计数据库
(3)使用缓存,把经常访问到的数据而且不需要经常变化的数据放在缓存中,能节约磁盘IO
(4)优化硬件;采用SSD,使用磁盘队列技术(RAID0,RAID1,RDID5)等;
(5)采用MySQL 内部自带的表分区技术,把数据分层不同的文件,能够提高磁盘的读取效率
(6)垂直分表;把一些不经常读的数据放在一张表里,节约磁盘I/O
(7)主从分离读写;采用主从复制把数据库的读操作和写入操作分离开来
(8)分库分表分机器(数据量特别大),主要的的原理就是数据路由
(9)选择合适的表引擎,参数上的优化
(10)进行架构级别的缓存,静态化和分布式
(11)不采用全文索引
(12)采用更快的存储方式,例如NoSql存储经常访问的数据
12.怎样解决海量数据的存储和访问造成系统设计瓶颈的问题?
(1)水平切分数据库:可以降低单台机器的负载,同时最大限度的降低了宕机造成的损失;分库降低了单点机器的负载;分表,提高了数据操作的效率,
(2)负载均衡策略:可以降低单台机器的访问负载,降低宕机的可能性;
(3)集群方案:解决了数据库宕机带来的单点数据库不能访问的问题;
(4)读写分离策略:最大限度的提高了应用中读取数据的速度和并发量;
13.怎样解决数据库高并发的问题?
(1)分表分库
(2)数据库索引
(3)redis缓存数据库
(4)读写分离
(5)负载均衡集群:将大量的并发请求分担到多个处理节点。由于单个处理节点的故障不影响整个服务,负载均衡集群同时也实现了高可用性。
14.数据库负载均衡
负载均衡集群是由一组相互独立的计算机系统构成,通过常规网络或专用网络进行连接, 由路由器衔接在一起, 各节点相互协作、 共同负载、 均衡压力, 对客户端来说,整个群集可以视为一台具有超高性能的独立服务器。
(1)实现原理
实现数据库的负载均衡技术,首先要有一个可以控制连接数据库的控制端。 在这里, 它截断了数据库和程序的直接连接, 由所有的程序来访问这个中间层, 然后再由中间层来访问数据库。这样, 我们就可以具体控制访问某个数据库了,然后还可以根据数据库的当前负载采取有效的均衡策略, 来调整每次连接到哪个数据库。
(2)实现多数据库数据同步
对于负载均衡,最重要的就是所有服务器的数据都是实时同步的。这是一个集群所必需的,因为, 如果数据不实时、 不同步, 那么用户从一台服务器读出的数据,就有别于从另一台服务器读出的数据, 这是不能允许的。 所以必须实现数据库的数据同步。 这样, 在查询的时候就可以有多个资源, 实现均衡。 数据同步完成后客户端才会得到响应, 同步过程是并发完成的,所以同步到多个数据库和同步到一个数据库的时间基本相等;另外同步的过程是在事务的环境下完成的, 保证了多份数据在任何时刻数据的一致性。 正因为 Moebius 中间件宿主在数据库中的创新,让中间件不但能知道数据的变化, 而且知道引起数据变化的 SQL 语句,根据 SQL 语句的类型智能的采取不同的数据同步的策略以保证数据同步成本的最小化。
数据条数很少, 数据内容也不大, 则直接同步数据数据条数很少, 但是里面包含大数据类型,比如文本, 二进制数据等, 则先对数据进行压缩然后再同步, 从而减少网络带宽的占用和传输所用的时间。
数据条数很多,此时中间件会拿到造成数据变化的 SQL 语句, 然后对 SQL 语句进行解析, 分析其执行计划和执行成本,并选择是同步数据还是同步 SQL 语句到其他的数据库中。此种情况应用在对表结构进行调整或者批量更改数据的时候非常有用。
(3)优缺点
优点:
(1)扩展性强:当系统要更高数据库处理速度时,只要简单地增加数据库服务器就可以得到扩展。
(2)可维护性:当某节点发生故障时,系统会自动检测故障并转移故障节点的应用,保证数据库的持续工作。
(3)安全性: 因为数据会同步的多台服务器上,可以实现数据集的冗余, 通过多份数据来保证安全性。另外它成功地将数据库放到了内网之中, 更好地保护了数据库的安全性。
(4)易用性:对应用来说完全透明,集群暴露出来的就是一个IP。
缺点:
(1) 不能够按照 Web 服务器的处理能力分配负载。
(2) 负载均衡器(控制端)故障, 会导致整个数据库系统瘫痪。
15.数据库备份怎么做,服务器挂了怎么办?
备份数据库:
shell> mysqldump -h host -u root -p dbname >dbname_backup.sql
恢复数据库:
shell> mysqladmin -h myhost -u root -p create dbname
shell> mysqldump -h host -u root -p dbname < dbname_backup.sql
16.如何把整个数据库导出来,再导入指定数据库中
导出:
mysqldump [-h主机] -u用户名 -p 数据库名 > 导出的数据库名.sql
导入指定的数据库中:
第一种方法:
mysqldump [-h主机] -u用户名 -p 数据库名 < 导出的数据库名.sql
第二种方法:
先创建好数据库,因为导出的文件里没有创建数据库的语句,如果数据库已经建好,则不用再创建。
create database example charset=utf8;(数据库名可以不一样)
切换数据库
use example;
导入指定sql文件
mysql>source /path/example.sql;
17.数据库怎么优化查询效率?
(1)储存引擎选择:如果数据表需要事务处理,应该考虑使用InnoDB,因为它完全符合ACID特性。如果不需要事务处理,使用默认存储引擎MyISAM是比较明智的
(2)分表分库,主从。
(3)对查询进行优化,要尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引
(4)应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描
(5)应尽量避免在 where 子句中使用 != 或 <> 操作符,否则将引擎放弃使用索引而进行全表扫描
(6)应尽量避免在 where 子句中使用 or 来连接条件,如果一个字段有索引,一个字段没有索引,将导致引擎放弃使用索引而进行全表扫描
(7)Update 语句,如果只更改1、2个字段,不要Update全部字段,否则频繁调用会引起明显的性能消耗,同时带来大量日志
(8)对于多张大数据量(这里几百条就算大了)的表JOIN,要先分页再JOIN,否则逻辑读会很高,性能很差。
18.如果每天有5T的用户数据量需要存入mysql中,怎么优化数据库?
- 1、尽量使数据库一次性写入Data File
- 2、减少数据库的checkpoint 操作
- 3、程序上尽量缓冲数据,进行批量式插入与提交
- 4、减少系统的IO冲突
19.如何查找MySQL中查询慢的SQL语句
(1)slow_query_log这个参数设置为ON,可以捕获执行时间超过一定数值的SQL语句。
(2)long_query_time当SQL语句执行时间超过此数值时,就会被记录到日志中,建议设置为1或者更短。
20.Python 中操作 Mysql 步骤
代码实现:
#首先安装包-pymysql sudo pip install pymysql
#之后在程序中调用
# from pymysql import *
''' connection 对象 用于建立与数据库的连接 创建对象:调用 connect()方法 '''
conn = connect(参数列表)
''' 参数列表:
host:连接 MySQL 主机,如果是本机则为”localhost“
port:连接 MySQL 主机端口,默认 3306
database:数据库名称
user:连接的用户名
password:连接的密码
charset:通信采用的编码方式,推荐采用 utf8
'''
''' connection 对象方法
close() 关闭连接
commit() 提交
rollback() 回滚
cursor() 返回
cursor 对象,用于执行 sql 语句
例如:select,insert,update,delete '''
cs1 = conn.cursor()
''' cursor 对象方法
close() 关闭
execute(operation[,parameters])执行语句,返回受影响的行数,主要用于执行 insert、update、delete 语句,
也可以执行 create、alter、drop 等语句
fetchone()执行查询语句时,获取查询结果集的第一个行数据,返回一个元组
fetchall()执行查询时,获取结果集的所有行,一行构成一个元组,再将这些元组装入一个元组返回 '''
'''
cursor 对象属性
rowcount 只读属性,表示最近一次
execute()执行后受影响的行数
connection 获得当前连接对象 '''
#例子
#创建 Connection 连接
conn = connect(host='localhost', port=3306, user='root', password='mysql', database='python1',
charset='utf8')
#获得 Cursor 对象 cs = conn.cursor()
# 更新 #
sql = 'update students set name="刘邦" where id=6'
#删除
# sql = 'delete from students where id=6'
#执行 select 语句,并返回受影响的行数:查询一条学生数据
sql = 'select id,name from students where id = 7'
# sql = 'SELECT id,name FROM students WHERE id = 7' count=cs.execute(sql)
#打印受影响的行数
print count
21.SQL 的 select 语句完整的执行顺序
SQL Select 语句完整的执行顺序:
1、from 子句组装来自不同数据源的数据;
2、where 子句基于指定的条件对记录行进行筛选;
3、group by 子句将数据划分为多个分组;
4、使用聚集函数进行计算;
5、使用 having 子句筛选分组;
6、计算所有的表达式;
7、select 的字段;
8、使用 order by 对结果集进行排序。
SQL 语言不同于其他编程语言的最明显特征是处理代码的顺序。在大多数据库语言中,代码按编码顺序被处理。但在 SQL 语句中,第一个被处理的子句式 FROM,而不是第一出现的 SELECT。
SQL 查询处理的步骤序号:
(1) FROM <left_table>
(2) <join_type> JOIN <right_table>
(3) ON <join_condition>
(4) WHERE <where_condition>
(5) GROUP BY <group_by_list>
(6) WITH {CUBE | ROLLUP}
(7) HAVING <having_condition>
(8) SELECT
(9) DISTINCT
(10) ORDER BY <order_by_list>
(11) <TOP_specification> <select_list>
以上每个步骤都会产生一个虚拟表,该虚拟表被用作下一个步骤的输入。这些虚拟表对调用者(客户端应用程序或者外部查询)不可用。只有最后一步生成的表才会会给调用者。如果没有在查询中指定某一个子句,将跳过相应的步骤。
逻辑查询处理阶段简介:
1、 FROM:对 FROM 子句中的前两个表执行笛卡尔积(交叉联接),生成虚拟表 VT1。
2、 ON:对 VT1 应用 ON 筛选器,只有那些使为真才被插入到 TV2。
3、 OUTER (JOIN):如果指定了 OUTER JOIN(相对于 CROSS JOIN 或 INNER JOIN),保留 表中未找到匹配的行将作为外部行添加到 VT2,生成 TV3。如果 FROM 子句包含两个以上的表, 则对上一个联接生成的结果表和下一个表重复执行步骤 1 到步骤 3,直到处理完所有的表位置。
4、 WHERE:对 TV3 应用 WHERE 筛选器,只有使为 true 的行才插入 TV4。
5、 GROUP BY:按 GROUP BY 子句中的列列表对 TV4 中的行进行分组,生成 TV5。
6、 CUTE|ROLLUP:把超组插入 VT5,生成 VT6。
7、 HAVING:对 VT6 应用 HAVING 筛选器,只有使为 true 的组插入到 VT7。
8、 SELECT:处理 SELECT 列表,产生 VT8。
9、 DISTINCT:将重复的行从 VT8 中删除,产品 VT9。
10、 ORDER BY:将 VT9 中的行按 ORDER BY 子句中的列列表顺序,生成一个游标(VC10)。
11、 TOP:从 VC10 的开始处选择指定数量或比例的行,生成表 TV11,并返回给调用者。 where 子句中的条件书写顺序
22.说一下 Mysql 数据库存储的原理?
储存过程是一个可编程的函数,它在数据库中创建并保存。它可以有 SQL 语句和一些特殊的控制结构组成。当希望在不同的应用程序或平台上执行相同的函数,或者封装特定功能时,存储过程是非常有用的。数据库中的存储过程可以看做是对编程中面向对象方法的模拟。它允许控制数据的访问方式。
存储过程通常有以下优点:
1、存储过程能实现较快的执行速度
2、存储过程允许标准组件是编程。
3、存储过程可以用流程控制语句编写,有很强的灵活性,可以完成复杂的判断和较复杂的运算。
4、存储过程可被作为一种安全机制来充分利用。
5、存储过程能够减少网络流量
23.Mysql 集群的优缺点?
优点:
- 99.999%的高可用性
- 快速的自动失效切换
- 灵活的分布式体系结构,没有单点故障
- 高吞吐量和低延迟
- 可扩展性强,支持在线扩容
缺点:
- 存在很多限制,比如:不支持外键
- 部署、管理、配置很复杂
- 占用磁盘空间大、内存大
- 备份和恢复不方便
- 重启的时候,数据节点将数据 load 到内存需要很长的时间
24.你用的 Mysql 是哪个引擎,各引擎之间有什么区别?
主要 MyISAM 与 InnoDB 两个引擎,其主要区别如下:
- InnoDB 支持事务,MyISAM 不支持,这一点是非常之重要。事务是一种高级的处理方式,如在一 些列增删改中只要哪个出错还可以回滚还原,而 MyISAM 就不可以了;
- MyISAM 适合查询以及插入为主的应用,InnoDB 适合频繁修改以及涉及到安全性较高的应用;
- InnoDB 支持外键,MyISAM 不支持;
- MyISAM 是默认引擎,InnoDB 需要指定;
- InnoDB 不支持 FULLTEXT 类型的索引;
- InnoDB 中不保存表的行数,如 select count() from table 时,InnoDB需要扫描一遍整个表来计算有多少行,但是 MyISAM 只要简单的读出保存好的行数即可。注意的是,当 count()语句包含 where 条件时 MyISAM 也需要扫描整个表;
- 对于自增长的字段,InnoDB 中必须包含只有该字段的索引,但是在 MyISAM 表中可以和其他字 段一起建立联合索引;
- 清空整个表时,InnoDB 是一行一行的删除,效率非常慢。MyISAM 则会重建表;
- InnoDB 支持行锁(某些情况下还是锁整表,如 update table set a=1 where user like '%lee%'
25.Mysql 数据库如何分区、分表?
分表可以通过三种方式:Mysql 集群、自定义规则和 merge 存储引擎。
分区有四类:
RANGE 分区:基于属于一个给定连续区间的列值,把多行分配给分区。
LIST 分区:类似于按 RANGE 分区,区别在于 LIST 分区是基于列值匹配一个离散值集合中的某个值来进行选择。
HASH 分区:基于用户定义的表达式的返回值来进行选择的分区,该表达式使用将要插入到表中的 这些行的列值进行计算。这个函数可以包含 MySQL 中有效的、产生非负整数值的任何表达式。
KEY 分区:类似于按 HASH 分区,区别在于 KEY 分区只支持计算一列或多列,且 MySQL 服务器 提供其自身的哈希函数。必须有一列或多列包含整数值。
26.如何对查询命令进行优化?
a. 应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索。
b. 应尽量避免在 where 子句中对字段进行 null 值判断,避免使用!=或<>操作符,避免使用 or 连接条件,或在 where 子句中使用参数、对字段进行表达式或函数操作,否则会导致权标扫描
c. 不要在 where 子句中的“=”左边进行函数、算术运算或其他表达式运算,否则系统将可能无法正确使用索引。
d. 使用索引字段作为条件时,如果该索引是复合索引,那么必须使用到该索引中的第一个字段作为 条件时才能保证系统使用该索引,否则该索引将不会被使用。
e. 很多时候可考虑用 exists 代替 in。
f. 尽量使用数字型字段。
g. 尽可能的使用 varchar/nvarchar 代替 char/nchar。
h. 任何地方都不要使用 select from t ,用具体的字段列表代替“”,不要返回用不到的任何字段。
i. 尽量使用表变量来代替临时表。
j. 避免频繁创建和删除临时表,以减少系统表资源的消耗。
k. 尽量避免使用游标,因为游标的效率较差。
l. 在所有的存储过程和触发器的开始处设置 SET NOCOUNT ON ,在结束时设置 SET NOCOUNT OFF。
m. 尽量避免大事务操作,提高系统并发能力。
n. 尽量避免向客户端返回大数据量,若数据量过大,应该考虑相应需求是否合理。
27.NoSQL 和关系数据库的区别?
a. SQL 数据存在特定结构的表中;而 NoSQL 则更加灵活和可扩展,存储方式可以省是 JSON 文档、 哈希表或者其他方式。
b. 在 SQL 中,必须定义好表和字段结构后才能添加数据,例如定义表的主键(primary key),索引 (index),触发器(trigger),存储过程(stored procedure)等。表结构可以在被定义之后更新,但是如果有比较大的结构变更的话就会变得比较复杂。在 NoSQL 中,数据可以在任何时候任何地方添加,不需要先定义表。
c. SQL 中如果需要增加外部关联数据的话,规范化做法是在原表中增加一个外键,关联外部数据表。 而在 NoSQL 中除了这种规范化的外部数据表做法以外,我们还能用如下的非规范化方式把外部数据直接放到原数据集中,以提高查询效率。缺点也比较明显,更新审核人数据的时候将会比较麻烦。
d. SQL 中可以使用 JOIN 表链接方式将多个关系数据表中的数据用一条简单的查询语句查询出来。 NoSQL 暂未提供类似 JOIN 的查询方式对多个数据集中的数据做查询。所以大部分NoSQL 使用非规范化的数据存储方式存储数据。
e. SQL 中不允许删除已经被使用的外部数据,而 NoSQL 中则没有这种强耦合的概念,可以随时删除任何数据。
f. SQL 中如果多张表数据需要同批次被更新,即如果其中一张表更新失败的话其他表也不能更新成 功。这种场景可以通过事务来控制,可以在所有命令完成后再统一提交事务。而 NoSQL 中没有事务这个概念,每一个数据集的操作都是原子级的。
g. 在相同水平的系统设计的前提下,因为 NoSQL 中省略了 JOIN 查询的消耗,故理论上性能上是 优于 SQL 的。
28.Mysql 数据库中怎么实现分页?
select * from table limit (start-1)*limit,limit;
其中 start 是页码,limit 是每页显示的条数。
29.sql 语句怎么看效率?
SQLServer2005-->新建一个查询-->输入语句 SELECT * FROM Person.Contact 执行(F5)-->Ctrl+L。
30.优化数据库?提高数据库的性能?
1. 对语句的优化
①用程序中,保证在实现功能的基础上,尽量减少对数据库的访问次数; 通过搜索参数,尽量减少对表的访问行数,最小化结果集,从而减轻网络负担;
②能够分开的操作尽量分开处理,提高每次的响应速度;在数据窗口使用 SQL 时,尽量把使用的索引放在选择的首列;算法的结构尽量简单;
③在查询时,不要过多地使用通配符如 SELECT * FROM T1 语句,要用到几列就选择几列如: SELECT COL1,COL2 FROM T1;
④在可能的情况下尽量限制尽量结果集行数如:SELECT TOP 300 COL1,COL2,COL3 FROM T1,因为某些情况下用户是不需要那么多的数据的。
⑤不要在应用中使用数据库游标,游标是非常有用的工具,但比使用常规的、面向集的 SQL 语句需要更大的开销;按照特定顺序提取数据的查找。
2. 避免使用不兼容的数据类型
例如 float 和 int、char 和 varchar、binary 和 varbinary 是不兼容的。
数据类型的不兼容可能使优化器无法执行一些本来可以进行的优化操作。
例如:
SELECT name FROM employee WHERE salary > 60000
在这条语句中,如 salary 字段是 money 型的,则优化器很难对其进行优化,因为 60000 是个整型数。我们应当在编程时将整型转化成为钱币型,而不要等到运行时转化。
若在查询时强制转换,查询速度会明显减慢。
3. 避免在 WHERE 子句中对字段进行函数或表达式操作。 若进行函数或表达式操作,将导致引擎放弃使用索引而进行全表扫描。
4. 避免使用!=或<>、IS NULL 或 IS NOT NULL、IN ,NOT IN 等这样的操作符
5. 尽量使用数字型字段
6. 合理使用 EXISTS,NOT EXISTS 子句。
7. 尽量避免在索引过的字符数据中,使用非打头字母搜索。
8. 分利用连接条件
9. 消除对大型表行数据的顺序存取
10. 避免困难的正规表达式
11. 使用视图加速查询
12. 能够用 BETWEEN 的就不要用 IN
13. DISTINCT 的就不用 GROUP BY
14. 部分利用索引
15. 能用 UNION ALL 就不要用 UNION
16. 不要写一些不做任何事的查询
17. 尽量不要用 SELECT INTO 语句
18. 必要时强制查询优化器使用某个索引
19. 虽然 UPDATE、DELETE 语句的写法基本固定,但是还是对 UPDATE 语句给点建议:
a) 尽量不要修改主键字段。
b) 当修改 VARCHAR 型字段时,尽量使用相同长度内容的值代替。
c) 尽量最小化对于含有 UPDATE 触发器的表的 UPDATE 操作。
d) 避免 UPDATE 将要复制到其他数据库的列。
e) 避免 UPDATE 建有很多索引的列。
f) 避免 UPDATE 在 WHERE 子句条件中的列。
31.提取数据库中倒数 10 条数据?
select top (10) * from table1 order by id desc。
32.Mysql 数据库的操作?
修改表-修改字段,重命名版:
- alter table 表名 change 原名 新名 类型及约束;
- alter table students change birthday birth datetime not null;
修改表-修改字段,不重名版本:
- alter table 表名 modify 列名 类型和约束;
- alter table students modify birth date not null
全列插入:
- insert into 表名 values(...) insert into students values(0,"郭靖", 1,"内蒙","2017-6");
部分插入:值的顺序与给出的列顺序对应:
- insert into students(name, birthday) values("黄蓉","2017-8");
修改:update 表名 set 列 1=值 1,列 2=值 2.。。where
- update students set gender=0, homwtown="古墓", where id = 5;
备份:mysqldump -uroot -p 数据库名 》 python.sql,
恢复:mysql -uroot -p 数据库名 < python.sql
33.数据库的设计?
第一范式:数据库表的每一列都是不可分割的原子数据项,即列不可拆分。
第二范式:建立在第一范式的基础上,要求数据库表中的每个实例或记录必须是可以唯一被区分的, 即唯一标识。
第三范式:建立在第二范式的基础上,任何非主属性不依赖与其他非主属性,即引用主键。
34.存储过程和函数的区别?
相同点:存储过程和函数都是为了可重复的执行操作数据库的 sql 语句的集合。
1)存储过程和函数都是一次编译,就会被缓存起来,下次使用就直接命中已经编译好的 sql 语句, 不需要重复使用。减少网络交互,减少网络访问流量。
不同点:标识符不同,函数的标识符是 function,存储过程是 proceduce。
1)函数中有返回值,且必须有返回值,而过程没有返回值,但是可以通过设置参数类型(in,out) 来实现多个参数或者返回值。
2)存储函数使用 select 调用,存储过程需要使用 call 调用。
3)select 语句可以在存储过程中调用,但是除了 select..into 之外的 select 语句都不能在函数中使 用。
4)通过 in out 参数,过程相关函数更加灵活,可以返回多个结果。
35.Mysql 日志
错误日志:记录启动,运行或者停止 mysql 时出现的问题;
通用日志:记录建立的客户端连接和执行的语句;
二进制日志:记录所有更改数据的语句;
慢查询日志:记录所有执行时间超过 long_query_time 秒的查询或者不适用索引的查询)。通过使用--slow_query_log[={0|1}]选项来启用慢查询日志,所有执行时间超多 long_query_time 的语句都会被记录。
36.数据库的一些基本操作命令(列举一些常用命令即可)?
MySQL 的常见命令如下:
1. create database name; 创建数据库
2. use databasename; 选择数据库
3. drop database name 直接删除数据库,不提醒
4. show tables; 显示表
5. describe tablename; 表的详细描述
6. select 中加上 distinct 去除重复字段
7. mysqladmin drop databasename 删除数据库前,有提示。
8. 显示当前 mysql 版本和当前日期 select version(),current_date;
MongoDB 的常见命令如下:
1. db.help(); Help 查看命令提示
2. use yourDB; 切换/创建数据库
3. show dbs; 查询所有数据库
4. db.dropDatabase(); 删除当前使用数据库
5. db.getName(); 查看当前使用的数据库
6. db.version(); 当前 db 版本
7. db.addUser("name"); 添加用户
8. db.addUser("userName", "pwd123", true);
9. show users; 显示当前所有用户
10. db.removeUser("userName"); 删除用户
11.db.yourColl.count(); 查询当前集合的数据条数
37.MongoDB的介绍
MongoDB 是一个面向文档的数据库系统。使用 C++编写,不支持 SQL,但有自己功能强大的查询语法。
MongoDB 使用 BSON 作为数据存储和传输的格式。BSON 是一种类似 JSON 的二进制序列化文档,支持嵌套对象和数组。
MongoDB 很像 MySQL,document 对应 MySQL 的 row,collection 对应 MySQL 的 table
应用场景:
a) 网站数据:mongo 非常适合实时的插入,更新与查询,并具备网站实时数据存储所需的复制及高度伸缩性。
b) 缓存:由于性能很高,mongo 也适合作为信息基础设施的缓存层。在系统重启之后, 由 mongo 搭建的持久化缓存可以避免下层的数据源过载。
c) 大尺寸、低价值的数据:使用传统的关系数据库存储一些数据时可能会比较贵,在此之前,很多程序员往往会选择传统的文件进行存储。
d) 高伸缩性的场景:mongo 非常适合由数十或者数百台服务器组成的数据库。
e) 用于对象及 JSON 数据的存储:mongo 的 BSON 数据格式非常适合文档格式化的存储及查询。
f) 重要数据:mysql,一般数据:mongodb,临时数据:memcache
g) 对于关系数据表而言,mongodb 是提供了一个更快速的视图 view;而对于 PHP 程序而言,mongodb 可以作为一个持久化的数组来使用,并且这个持久化的数组还可 以支持排序、条件、限制等功能。
h) 将 mongodb 代替 mysql 的部分功能,主要一个思考点就是:把 mongodb 当作 mysql 的一个 view(视图),view 是将表数据整合成业务数据的关键。比如说对原始数据进行报表,那么就要先把原始数据统计后生成 view,在对 view 进行查询和报表。
不适合的场景:
a) 高度事物性的系统:例如银行或会计系统。传统的关系型数据库目前还是更适用于需要大量原子性复杂事务的应用程序。
b) 传统的商业智能应用:针对特定问题的 BI 数据库会对产生高度优化的查询方式。对于此类应用,数据仓库可能是更合适的选择。
c) 需要 SQL 的问题
d) 重要数据,关系数据
优点:
1)弱一致性(最终一致),更能保证用户的访问速度
2)文档结构的存储方式,能够更便捷的获取数
3)内置 GridFS,高效存储二进制大对象 (比如照片和视频)
4)支持复制集、主备、互为主备、自动分片等特性
5)动态查询
6)全索引支持,扩展到内部对象和内嵌数组
缺点:
1)不支持事务
2)MongoDB 占用空间过大,维护工具不够成熟
38.MongoDB 成为优秀的 NoSQL 数据库的原因是什么?
以下特点使得 MongoDB 成为优秀的 NoSQL 数据库:
1)面向文件的
2)高性能
3)高可用性
4)易扩展性
5)丰富的查询语言
6)可分片
7)对数据存储友好
39.分析器在 MongoDB 中的作用是什么?
MongoDB 中包括了一个可以显示数据库中每个操作性能特点的数据库分析器。通过这个分析器你可以找到比预期慢的查询(或写操作);利用这一信息,比如,可以确定是否需要添加索引。
40.MySQL 与 MongoDB 本质之间最基本的差别是什么
差别在多方面,例如:数据的表示、查询、关系、事务、模式的设计和定义、速度和性能。
MongoDB 是由 C++语言编写的,是一个基于分布式文件存储的开源数据库系统。在高负载的情况下,添加更多的节点,可以保证服务器性能。
MongoDB 旨在为 WEB 应用提供可扩展的高性能数据存储解决方案。
MongoDB 将数据存储为一个文档,数据结构由键值(key=>value)对组成。MongoDB 文档类似于 JSON 对象。字段值可以包含其他文档,数组及文档数组。
MongoDB 是一个面向文档的数据库,目前由 10gen 开发并维护,它的功能丰富齐全,所以完全 可以替代 MySQL。
与 MySQL 等关系型数据库相比,MongoDB 的优点如下:
①弱一致性,更能保证用户的访问速度。
②文档结构的存储方式,能够更便捷的获取数据。
③内置 GridFS,支持大容量的存储。
④内置 Sharding。
⑤第三方支持丰富。(这是与其他的 NoSQL 相比,MongoDB 也具有的优势)
⑥性能优越:
MongoDB 本身它还算比较年轻的一个产品,所以它的问题,就是成熟度肯定没有传统 MySQL 那么成熟稳定。所以在使用的时候,
第一,尽量使用稳定版,不要在线上使用开发版,这是一个大原则;
另外一点,备份很重要,MongoDB 如果出现一些异常情况,备份一定是要能跟上。除了通过传统的复制的方式来做备份,离线备份也还是要有,不管你是用什么方式,都要有一个完整的离线备份。 往往最后出现了特殊情况,它能帮助到你;
另外,MongoDB 性能的一个关键点就是索引,索引是不是能有比较好的使用效率,索引是不是能够放在内存中,这样能够提升随机读写的性能。如果你的索引不能完全放在内存中,一旦出现随机 读写比较高的时候,它就会频繁地进行磁盘交换,这个时候,MongoDB 的性能就会急剧下降,会出现波动。
另外,MongoDB 还有一个最大的缺点,就是它占用的空间很大,因为它属于典型空间换时间原则的类型。那么它的磁盘空间比普通数据库会浪费一些,而且到目前为止它还没有实现在线压缩功能, 在 MongoDB 中频繁的进行数据增删改时,如果记录变了,例如数据大小发生了变化,这时候容易产生一些数据碎片,出现碎片引发的结果,一个是索引会出现性能问题,
另外一个就是在一定的时间后,所占空间会莫明其妙地增大,所以要定期把数据库做修复,定期重新做索引,这样会提升 MongoDB 的稳定性和效率。在最新的版本里,它已经在实现在线压缩, 估计应该在 2.0 版左右,应该能够实现在线压缩,可以在后台执行现在 repair DataBase 的一些操作。 如果那样,就解决了目前困扰我们的大问题。
41.Redis 中 list 底层实现有哪几种?有什么区别?
列表对象的编码可以是 ziplist 或者 linkedlist
ziplist 是一种压缩链表,它的好处是更能节省内存空间,因为它所存储的内容都是在连续的内存区域当中的。当列表对象元素不大,每个元素也不大的时候,就采用 ziplist 存储。但当数据量过大 时就 ziplist 就不是那么好用了。因为为了保证他存储内容在内存中的连续性,插入的复杂度是 O(N),即每次插入都会重新进行realloc。如下图所示,对象结构中ptr所指向的就是一个ziplist。整个ziplist 只需要 malloc 一次,它们在内存中是一块连续的区域。
42.怎样解决数据库高并发的问题?
解决数据库高并发的常见方案:
1) 缓存式的 Web 应用程序架构:
在 Web 层和 DB(数据库)层之间加一层 cache 层,主要目的:减少数据库读取负担,提高数据读取速度。cache 存取的媒介是内存,可以考虑采用分布式的 cache 层,这样更容易破除内存容量 的限制,同时增加了灵活性。
2) 增加 Redis 缓存数据库
3) 增加数据库索引
4) 页面静态化:
效率最高、消耗最小的就是纯静态化的 html 页面,所以我们尽可能使我们的网站上的页面采用静态页面来实现,这个最简单的方法其实也是最有效的方法。用户可以直接获取页面,不用像 MVC 结构走那么多流程,比较适用于页面信息大量被前台程序调用,但是更新频率很小的情况。
5) 使用存储过程:
处理一次请求需要多次访问数据库的操作,可以把操作整合到储存过程,这样只要一次数据库访问就可以了。
6) MySQL 主从读写分离:
当数据库的写压力增加,cache 层(如 Memcached)只能缓解数据库的读取压力。读写集中在一个数据库上让数据库不堪重负。使用主从复制技术(master-slave 模式)来达到读写分离,以提高读写性能和读库的可扩展性。读写分离就是只在主服务器上写,只在从服务器上读,基本原理是 让主数据库处理事务性查询,而从数据库处理 select 查询,数据库复制被用于把事务性查询(增删改) 导致的改变更新同步到集群中的从数据库。
MySQL 读写分离提升系统性能:
1、主从只负责各自的读和写,极大程度缓解 X 锁和 S 锁争用。
2、slave 可以配置 MyISAM 引擎,提升查询性能以及节约系统开销。
3、master 直接写是并发的,slave 通过主库发送来的 binlog 恢复数据是异步的。
4、slave 可以单独设置一些参数来提升其读的性能。
5、增加冗余,提高可用性。
实现主从分离可以使用 MySQL 中间件如:Atlas
7) 分表分库:
在 cache 层的高速缓存,MySQL 的主从复制,读写分离的基础上,这时 MySQL 主库的写压力开始出现瓶颈,而数据量的持续猛增,由于 MyISAM 使用表锁,在高并发下会出现严重的锁问题,大量的高并发 MySQL 应用开始使用 InnoDB 引擎代替 MyISAM。采用 Master-Slave 复制模式的 MySQL 架构,只能对数据库的读进行扩展,而对数据的写操作还是集中在 Master 上。这时需要 对数据库的吞吐能力进一步地扩展,以满足高并发访问与海量数据存储的需求。
对于访问极为频繁且数据量巨大的单表来说,首先要做的是减少单表的记录条数,以便减少数据查询所需的时间,提高数据库的吞吐,这就是所谓的分表【水平拆分】。在分表之前,首先需要选择适当的分表策略(尽量避免分出来的多表关联查询),使得数据能够较为均衡地分布到多张表中, 并且不影响正常的查询。
分表能够解决单表数据量过大带来的查询效率下降的问题,但是却无法给数据库的并发处理 能力带来质的提升。面对高并发的读写访问,当数据库 master 服务器无法承载写操作压力时,不管如何扩展 Slave 服务器都是没有意义的,对数据库进行拆分,从而提高数据库写入能力,即分库【垂 直拆分】。
8) 负载均衡集群:
将大量的并发请求分担到多个处理节点。由于单个处理节点的故障不影响整个服务,负载均衡集群同时也实现了高可用性。
负载均衡将是大型网站解决高负荷访问和大量并发请求采用的终极解决办法。
43.Redis 数据库,内容是以何种结构存放在 Redis 中的?
String(字符串),Hash(哈希),List(列表),Set(集合)及 zset(sortedset:有序集合)。
44.Redis 的并发竞争问题怎么解决?
方案一:可以使用独占锁的方式,类似操作系统的 mutex 机制,不过实现相对复杂,成本较高。
方案二:使用乐观锁的方式进行解决(成本较低,非阻塞,性能较高)
如何用乐观锁方式进行解决? 本质上是假设不会进行冲突,使用 redis 的命令 watch 进行构造条件
45.Redis 基本类型、相关方法
Redis 支持五种数据类型:string(字符串)、hash(哈希)、list(列表)、set(集合)及 zset(sorted set:有序集合)。
一、 String
1.String 是 Redis 最为常用的一种数据类型,String 的数据结构为 key/value 类型,String 可以包含任何数据。
2.常用命令: set,get,decr,incr,mget 等。
二、 Hash
1.Hash 类型可以看成是一个 key/value 都是 String 的 Map 容器。
2.常用命令:hget,hset,hgetall 等。
三、 List
1.List 用于存储一个有序的字符串列表,常用的操作是向队列两端添加元素或者获得列表的某一片 段。
2.常用命令:lpush,rpush,lpop,rpop,lrange 等
四、 Set
1.Set 可以理解为一组无序的字符集合,Set 中相同的元素是不会重复出现的,相同的元素只保留 一个。
2.常用命令:sadd,spop,smembers,sunion 等。
五、 Sorted Set(有序集合)
1.有序集合是在集合的基础上为每一个元素关联一个分数,Redis 通过分数为集合中的成员进行排 序。
2.常用命令:zadd,zrange,zrem,zcard 等。
46.Redis 的事务?
一、 Redis 事务允许一组命令在单一步骤中执行。事务有两个属性,说明如下:
a) 事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。
b) Redis 事务是原子的。原子意味着要么所有的命令都执行,要么都不执行;
二、 一个事务从开始到执行会经历以下三个阶段:
a)开始事务
b)命令入队
c)执行事务
47.Redis 的使用场景有哪些?
1. 取最新 N 个数据的操作
2. 排行榜应用,取 TOP N 操作
3. 需要精准设定过期时间的应用
4. 计数器应用
5. uniq 操作,获取某段时间所有数据排重值
6. Pub/Sub 构建实时消息系统
7. 构建队列系统
8. 缓存
48.Redis 默认端口,默认过期时间,Value 最多可以容纳的数据长度?
1. 默认端口:6379
2. 默认过期时间:可以说永不过期,一般情况下,当配置中开启了超出最大内存限制就写磁盘的 话,那么没有设置过期时间的 key 可能会被写到磁盘上。假如没设置,那么 REDIS 将使用 LRU 机制,将内存中的老数据删除,并写入新数据。
3. Value 最多可以容纳的数据长度是:512M。
49.Redis 有多少个库?
Redis 一个实例下有 16 个。
50.请拿出 B 表中的 accd,(A 表中和 B 表中的一样的数据)?
select * from B inner join on B.name = A.name
51.关系型数据库中,表和表之间有左连接,内连接,外连接,分别解释下他们的含义和区别?
内连接查询:查询的结果为两个表匹配到的数据。
右接查询:查询的结果为两个表匹配到的数据,右表特有的数据,对于左表中不存在的数据使用null 填充。
左连接查询:查询的结果为两个表匹配到的数据,左表特有的数据,对于右表中不存在的数据使用null 填充。
52.Mysql 中 myisam 与 innodb 的区别?
1、 存储结构
MyISAM:每个 MyISAM 在磁盘上存储成三个文件。第一个文件的名字以表的名字开始,扩展名指 出文件类型。.frm 文件存储表定义。数据文件的扩展名为.MYD (MYData)。索引文件的扩展名是.MYI (MYIndex)。
InnoDB:所有的表都保存在同一个数据文件中(也可能是多个文件,或者是独立的表空间文件), InnoDB 表的大小只受限于操作系统文件的大小,一般为 2GB。
2、 存储空间
MyISAM:可被压缩,存储空间较小。支持三种不同的存储格式:静态表(默认,但是注意数据末尾 不能有空格,会被去掉)、动态表、压缩表。
InnoDB:需要更多的内存和存储,它会在主内存中建立其专用的缓冲池用于高速缓冲数据和索引。
3、 事务支持
MyISAM:强调的是性能,每次查询具有原子性,其执行数度比 InnoDB 类型更快,但是不提供事务 支持。
InnoDB:提供事务支持事务,外部键等高级数据库功能。 具有事务(commit)、回滚(rollback)和 崩溃修复能力(crash recovery capabilities)的事务安全(transaction-safe (ACID compliant))型表。
4、 CURD 操作
MyISAM:如果执行大量的 SELECT,MyISAM 是更好的选择。(因为没有支持行级锁),在增删的 时候需要锁定整个表格,效率会低一些。相关的是 innodb 支持行级锁,删除插入的时候只需要锁定改行就行,效率较高
InnoDB:如果你的数据执行大量的 INSERT 或 UPDATE,出于性能方面的考虑,应该使用 InnoDB 表。DELETE 从性能上 InnoDB 更优,但 DELETE FROM table 时,InnoDB 不会重新建立表,而是一 行一行的删除,在 innodb 上如果要清空保存有大量数据的表,最好使用 truncate table 这个命令。
5、 外键
MyISAM:不支持
InnoDB:支持
53.MySQL索引都有哪些分类?
按数据结构分类可分为:B+tree索引、Hash索引、Full-text索引。
按物理存储分类可分为:聚簇索引、二级索引(辅助索引)。
按字段特性分类可分为:主键索引、普通索引、前缀索引。
按字段个数分类可分为:单列索引、联合索引(复合索引、组合索引)。
54.什么是索引?
索引是对数据库表中一列或多列的值进行排序的一种结构,使用索引可快速访问数据库表中的特定信息。
55.索引作用是什么?
索引的作用相当于图书的目录,可以根据目录中的页码快速找到所需的内容,提高性能(查询速度)。
56.mysql索引 索引优缺点
优点:
1.通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。
2.可以大大加快数据的检索速度,这也是创建索引的最主要的原因。
3.可以加速表和表之间的连接,特别是在实现数据的参考完整性方面特别有意义。
4.在使用分组和排序子句进行数据检索时,同样可以显著减少查询中分组和排序的时间。
5.通过使用索引,可以在查询的过程中,使用优化隐藏器,提高系统的性能。
缺点:
1.创建索引和维护索引要耗费时间,这种时间随着数据量的增加而增加。
2.索引需要占物理空间,除了数据表占数据空间之外,每一个索引还要占一定的物理空间,如果要建立聚集索引那么需要的空间就会更大。
3.当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,这样就降低了数据的维护速度。
因为索引非常占内存,所以索引也需要谨慎添加,那些字段需要索引。
57.索引建立原则
(1). 尽量减少like,但不是绝对不可用,”xxxx%” 是可以用到索引的
(2). 表的主键、外键必须有索引
(3). 谁的区分度更高(同值的最少),谁建索引,区分度的公式是count(distinct(字段))/count(*)
(4). 单表数据太少,不适合建索引
(5). where,order by ,group by 等过滤时,后面的字段最好加上索引
(6). 如果既有单字段索引,又有这几个字段上的联合索引,一般可以删除联合索引;
(7). 联合索引的建立需要进行仔细分析;尽量考虑用单字段索引代替:
(8). 联合索引: mysql 从左到右的使用索引中的字段,一个查询可以只使用索引中的一部份,但只能是最左侧部分。
(9). 前缀索引: 有时候需要索引很长的字符列,这会让索引变得大且慢。通常可以索引开始的部分字符,这样可以大大节约索引空间,从而提高索引效率。其缺点是不能用于ORDER BY和GROUP BY操作,也不能用于覆盖索引 Covering index(即当索引本身包含查询所需全部数据时,不再访问数据文件本身)。
(10). NULL会导致索引形同虚设
(11). 对于查询频率高的字段创建索引;
(12). 索引的数目不宜太多
【不需要建立索引情况】
- 频繁更新的字段不适合创建索引
- Where条件里用不到的字段不创建索引
- 表记录太少
- 经常增删改的表
- 数据重复且分布平均的表字段,如果某个数据列包含许多重复的内容,为它建立索引就没有太大的实际效果
58.什么是并发控制,什么是乐观锁,什么是悲观锁?
当程序中可能出现并发的情况时,就需要保证在并发情况下数据的准确性,以此确保当前用户和其他用户一起操作时,所得到的结果和他单独操作时的结果是一样的。这就叫做并发控制。
并发控制的目的是保证一个用户的工作不会对另一个用户的工作产生不合理的影响。
实现并发控制的主要手段分为乐观并发控制和悲观并发控制两种。
乐观锁比较适用于读多写少的情况(多读场景),悲观锁比较适用于写多读少的情况(多写场景)。
悲观锁(Pessimistic Lock):
当要对数据库中的一条数据进行修改的时候,为了避免同时被其他人修改,最好的办法就是直接对该数据进行加锁以防止并发。这种借助数据库锁机制,在修改数据之前先锁定,再修改的方式被称之为悲观并发控制
悲观锁主要分为共享锁和排他锁:
共享锁【shared locks】又称为读锁,简称 S 锁。顾名思义,共享锁就是多个事务对于同一数据可以共享一把锁,都能访问到数据,但是只能读不能修改。
排他锁【exclusive locks】又称为写锁,简称 X 锁。顾名思义,排他锁就是不能与其他锁并存,如果一个事务获取了一个数据行的排他锁,其他事务就不能再获取该行的其他锁,包括共享锁和排他锁。获取排他锁的事务可以对数据行读取和修改。
乐观锁(Optimistic Locking)
乐观锁是相对悲观锁而言的,乐观锁假设数据一般情况不会造成冲突,所以在数据进行提交更新的时候,才会正式对数据的冲突与否进行检测,如果冲突,则返回给用户异常信息,让用户决定如何去做。乐观锁适用于读多写少的场景,这样可以提高程序的吞吐量。
59.redis是单线程还是多线程,为什么?
不同版本的Redis是不同的,Redis4.0之前是单线程运行的,但单线程并不代表效率低,像Nginx、Nodejs也是单线程程序,但是它们的效率并不低;Redis4.0后开始支持多线程,比如后台删除等功能。。
Redis4.0之前使用单线程的原因:
1、单线程模式方便开发和调试;
2、Redis内部使用了基于epoll的多路复用;
3、Redis主要的性能瓶颈是内存或网络带宽,而非cpu。
60.Redis为什么这么快?
原因有以下几点:
a.基于内存操作:Redis的所有数据都存在内存中,因此所有的运算都是内存级别的,所以它的性能比较高。
b.数据结构简单:Redis的数据结构比较简单,是为Redis专门设计的,而这些简单的数据结构的查找和操作的时间复杂度都是O(1)。
c.多路复用和非阻塞IO:Redis使用IO多路复用功能来监听多个socket连接的客户端,这样就可以使用一个线程来处理多个情况,从而减少线程切换带来的开销,同时也避免了IO阻塞操作,从而大大提高了Redis的性能。
d.避免上下文切换:因为是单线程模型,因此就避免了不必要的上下文切换和多线程竞争,这就省去了多线程切换带来的时间和性能上的开销,而且单线程不会导致死锁的问题发生。 官方使用的基准测试结果表明,单线程的Redis可以达到10W/S的吞吐量。
61.IO多路复用是什么?
套接字的读写方法默认是阻塞的,例如当调用读取操作read方法时,缓冲区没有任何数据,那么这个线程会卡在这里,直到缓冲区有数据或者连接被关闭时,read方法才会返回,该线程才能继续处理其他业务。
但这样显然就降低了程序的执行效率,而Redis使用的时非阻塞的IO,这就意味着IO的读写流程不再是阻塞的,读写方法都是瞬间完成并且返回的,也就是它会采用能读多少就读多少、能写多少就写多少的策略来执行IO操作,这显然更符合我们对性能的追求。
但这种非阻塞的IO也面临一个问题,那就是当我们执行读取操作时,有可能只读取了一部分数据;同理写数据也是这种情况,当缓冲区满了,而我们的数据还没有写完,那么生效的数据何时写就成了一个问题。
而IO的多路复用就是解决上面的这个问题的,使用IO多路复用最简单的方式就是使用select函数,此函数是操作系统提供给用户程序的API接口,用于监控多个文件描述符的可读和可写情况的,这样就可以监控到文件描述符的读写事件了。当监控到相应的事件之后就可以通知线程处理相应的业务了,这样就保证了Redis读写功能的正常执行。
62.Redis6.0中的多线程?
使用Redis多线程就可以分摊Redis同步读写IO的压力,以及充分利用多核CPU资源,并且可以有效的提升Redis的QPS。
Redis6.0中新增了多线程的功能来提高IO的读写性能,它的主要实现思路是将主线程的IO读写任务拆分给一组独立的线程去执行,这样就可以使用多个socket的读写并行化了,但Redis的命令依旧是主线程串行执行的。
63.mysql索引为啥用b+树而不用b树?
- b+树的数据都集中在叶子节点。分支节点 只负责索引。 b树的分支节点也有数据 。
- b+树更擅长范围查询。叶子节点数据是按顺序放置的双向链表。 b树范围查询只能中序遍历。
- 索引节点没有数据。比较小。b树可以把索引完全加载至内存中。
64.MySql的隔离级别有:
- 串行化(Serializable): 可避免脏读,不可重复读,幻读
- 可重复读(Repeatable read):可避免脏读,不可重复读 这是默认的隔离级别
- 读已提交(Read committed):可避免脏读
- 读未提交(Read uncommitted):无法保证任何操作
65.主键和外键的区别?
表中经常有一个列或多个列的组合,其值能唯一的标识表中的每一行。这样的一列或多列称为表的主键。
外键:用来表示表与表之间联系,是表中的一个列。
主键和外键都是用于维护数据库完整性的一种机制。
区别:
1、主键是唯一标识一条记录,不能重复,不允许为空;而外键可以重复,可以是空值;
2、主键是用来保持数据完整性,外键是用来建立与其他表联系用的;
3、主键只有一个,外键可以有多个。
66.事务与锁的关系?
事务与锁是不同的。
事务具有ACID( 原子性、一致性、隔离性和持久性),锁是用于解决隔离性的一种机制。
事务的隔离级别通过锁的机制来实现。另外锁有不同的粒度,同时事务也是有不同的隔离级别的(一般有四种:读未提交Read uncommitted, 读已提交Read committed, 可重复读Repeatable read, 可串行化Serializable)。
在具体的程序设计中,开启事务其实是要数据库支持才行的,如果数据库本身不支持事务,那么仍然无法确保你在程序中使用的事务是有效的。
锁可以分为乐观锁和悲观锁:
悲观锁:认为在修改数据库数据的这段时间里存在着也想修改此数据的事务;
乐观锁:认为在短暂的时间里不会有事务来修改此数据库的数据; 我们一般意义上讲的锁其实是指悲观锁,在数据处理过程中,将数据置于锁定状态(由数据库实现)。
如果开启了事务,在事务没提交之前,别人是无法修改该数据的;如果rollback,你在本次事务中的修改将撤消(不是别人修改的会没有,因为别人此时无法修改)。当然,前提是你使用的数据库支持事务。还有一个要注意的是,部分数据库支持自定义SQL锁覆盖事务隔离级别默认的锁机制,如果使用了自定义的锁,那就另当别论。 重点:一般事务使用的是悲观锁(具有排他性)。
67. 数据库设计范式?
范式: 对设计数据库提出的一些规范,目前有迹可寻的共有8种范式,一般遵守3范式即可。
第一范式(1NF): 强调的是列的原子性,即列不能够再分成其他几列。(1NF强调字段是最小单元,不可再分)
第二范式(2NF): 满足 1NF,另外包含两部分内容,一是表必须有一个主键;二是非主键字段必须完全依赖于主键,而不能只依赖于主键的一部分。(2NF强调在1NF基础上必须要有主键和非主键字段必须完全依赖于主键,也就是说 不能部分依赖)
第三范式(3NF): 满足 2NF,另外非主键列必须直接依赖于主键,不能存在传递依赖。即不能存在:非主键列 A 依赖于非主键列 B,非主键列 B 依赖于主键的情况。 (3MF强调在2NF基础上 非主键字段必须直接依赖于主键,也就是说不能传递依赖(间接依赖))
68.MySQL主要有几种索引类型
1.普通索引
2.唯一索引
3.主键索引
4.组合索引
5.全文索引
69.Redis的持久化
持久化:就是把内存中的数据保存到磁盘
一:Redis为什么要有持久化?
由于Redis是一个基于内存的数据库,因此数据容易丢失,为了解决数据丢失的问题,于是Redis就设计了持久化
二.Redis的持久的方式有哪些?
有两个,分别是rdb和aof的持久化方式
三.分别介绍一下Redis的持久化方式的机制
rdb持久化:Redis为我们提供了一个rdb的持久化方式具体每隔一定时间,或者当key的改变达到一定的数量的时候,就会自动往磁盘保存一次
aof持久化:Redis还为我们提供了一个aof的持久化方式,这种方式是通过记录用户的操作过程(用户每执行一次命令,就会被Redis记录在XXX.aof文件里,如果突然断电了,Redis的数据就会通过重新读取并执行XXX.aof里的命令记录来恢复数据)来恢复数据
四.两种Redis持久化方式的优缺点
都是为了防止数据丢失
rdb:假如三种方式没有一种被满足,触发不了保存,突然断电,那就会丢失数据
aof:为了解决rdb的弊端,就有了aof的持久化,始终在一个文件里保存记录,但aof的持久化随着时间的推移数据量会越来越大,占用很大的空间
70.redis缓存和mysql数据库如何保证数据一致性?
一.需求起因:
在高并发的业务场景下,数据库大多数情况都是用户并发访问最薄弱的环节。所以,就需要使用redis做一个缓冲操作,让请求先访问到redis,而不是直接访问MySQL等数据库。
这个业务场景,主要是解决读数据从Redis缓存,一般都是按照下图的流程来进行业务操作。
读取缓存步骤一般没有什么问题,但是一旦涉及到数据更新:数据库和缓存更新,就容易出现缓存(Redis)和数据库(MySQL)间的数据一致性问题。
不管是先写MySQL数据库,再删除Redis缓存;还是先删除缓存,再写库,都有可能出现数据不一致的情况。举一个例子:
1.如果删除了缓存Redis,还没有来得及写库MySQL,另一个线程就来读取,发现缓存为空,则去数据库中读取数据写入缓存,此时缓存中为脏数据。
2.如果先写了库,在删除缓存前,写库的线程宕机了,没有删除掉缓存,则也会出现数据不一致情况。
因为写和读是并发的,没法保证顺序,就会出现缓存和数据库的数据不一致的问题。
二.缓存和数据库一致性解决方案
1.第一种方案:采用延时双删策略
在写库前后都进行redis.del(key)操作,并且设定合理的超时时间。
具体的步骤就是:
- 先删除缓存;
- 再写数据库;
- 休眠500毫秒;
- 再次删除缓存。
那么,这个500毫秒怎么确定的,具体该休眠多久呢?
需要评估自己的项目的读数据业务逻辑的耗时。这么做的目的,就是确保读请求结束,写请求可以删除读请求造成的缓存脏数据。
当然这种策略还要考虑redis和数据库主从同步的耗时。最后的的写数据的休眠时间:则在读数据业务逻辑的耗时基础上,加几百ms即可。比如:休眠1秒。
设置缓存过期时间
从理论上来说,给缓存设置过期时间,是保证最终一致性的解决方案。所有的写操作以数据库为准,只要到达缓存过期时间,则后面的读请求自然会从数据库中读取新值然后回填缓存。
该方案的弊端
结合双删策略+缓存超时设置,这样最差的情况就是在超时时间内数据存在不一致,而且又增加了写请求的耗时。
2、第二种方案:异步更新缓存(基于订阅binlog的同步机制)
技术整体思路:
MySQL binlog增量订阅消费+消息队列+增量数据更新到redis
- 读Redis:热数据基本都在Redis
- 写MySQL:增删改都是操作MySQL
- 更新Redis数据:MySQ的数据操作binlog,来更新到Redis
Redis更新
1)数据操作主要分为两大块:
- 一个是全量(将全部数据一次写入到redis)
- 一个是增量(实时更新)
这里说的是增量,指的是mysql的update、insert、delate变更数据。
2)读取binlog后分析 ,利用消息队列,推送更新各台的redis缓存数据。
这样一旦MySQL中产生了新的写入、更新、删除等操作,就可以把binlog相关的消息推送至Redis,Redis再根据binlog中的记录,对Redis进行更新。
其实这种机制,很类似MySQL的主从备份机制,因为MySQL的主备也是通过binlog来实现的数据一致性。
这里的消息推送工具可以采用第三方工具:kafka、rabbitMQ等来实现推送更新Redis。