1. 如何进行SQL优化
(1)选择正确的存储引擎
以 MySQL为例,包括有两个存储引擎 MyISAM 和 InnoDB,每个引擎都有利有弊。
MyISAM 适合于一些需要大量查询的应用,但其对于有大量写操作并不是很好。甚至你只是需要update一个字段,整个表都会被锁起来,而别的进程,就算是读进程都无法操作直到读操作完成。另外,MyISAM 对于 SELECT COUNT(*) 这类的计算是超快无比的。
InnoDB 的趋势会是一个非常复杂的存储引擎,对于一些小的应用,它会比 MyISAM 还慢。但是它支持“行锁” ,于是在写操作比较多的时候,会更优秀。并且,他还支持更多的高级应用,比如:事务。
(2)优化字段的数据类型
记住一个原则,越小的列会越快。如果一个表只会有几列罢了(比如说字典表,配置表),那么,我们就没有理由使用 INT 来做主键,使用 MEDIUMINT, SMALLINT 或是更小的 TINYINT 会更经济一些。如果你不需要记录时间,使用 DATE 要比 DATETIME 好得多。当然,你也需要留够足够的扩展空间。
(3)为搜索字段添加索引
索引并不一定就是给主键或是唯一的字段。如果在你的表中,有某个字段你总要会经常用来做搜索,那么最好是为其建立索引,除非你要搜索的字段是大的文本字段,那应该建立全文索引。
(4)避免使用Select 从数据库里读出越多的数据
*那么查询就会变得越慢。并且,如果你的数据库服务器和WEB服务器是两立的服务器的话,这还会增加网络传输的负载。即使你要查询数据表的所有字段,也尽量不要用*通配符,善用内置提供的字段排除定义也许能给带来更多的便利。
(5)使用 ENUM 而不是 VARCHAR
ENUM 类型是非常快和紧凑的。在实际上,其保存的是 TINYINT,但其外表上显示为字符串。这样一来,用这个字段来做一些选项列表变得相当的完美。例如,性别、民族、部门和状态之类的这些字段的取值是有限而且固定的,那么,你应该使用 ENUM 而不是 VARCHAR。
(6)尽可能的使用 NOT NULL
除非你有一个很特别的原因去使用 NULL 值,你应该总是让你的字段保持 NOT NULL。 NULL其实需要额外的空间,并且,在你进行比较的时候,你的程序会更复杂。 当然,这里并不是说你就不能使用NULL了,现实情况是很复杂的,依然会有些情况下,你需要使用NULL值。
(7)固定长度的表会更快
如果表中的所有字段都是“固定长度”的,整个表会被认为是 “static” 或 “fixed-length”。 例如,表中没有如下类型的字段: VARCHAR,TEXT,BLOB。只要你包括了其中一个这些字段,那么这个表就不是“固定长度静态表”了,这样,MySQL 引擎会用另一种方法来处理。
固定长度的表会提高性能,因为MySQL搜寻得会更快一些,因为这些固定的长度是很容易计算下一个数据的偏移量的,所以读取的自然也会很快。而如果字段不是定长的,那么,每一次要找下一条的话,需要程序找到主键。
并且,固定长度的表也更容易被缓存和重建。不过,唯一的副作用是,固定长度的字段会浪费一些空间,因为定长的字段无论你用不用,他都是要分配那么多的空间
2. 实践中如何优化MySQL
从效果上第一条影响最大,后面越来越小。
① SQL语句及索引的优化
② 数据库表结构的优化
③ 系统配置的优化
④ 硬件的优化
3. MySQL数据库作发布系统的存储,一天五万条以上的增量,预计运维三年,怎么优化
a. 设计良好的数据库结构,允许部分数据冗余,尽量避免join查询,提高效率。
b. 选择合适的表字段数据类型和存储引擎,适当的添加索引。
c. mysql库主从读写分离。
d. 找规律分表,减少单表中的数据量提高查询速度。
e。添加缓存机制,比如memcached,apc等。
f. 不经常改动的页面,生成静态页面。
g. 书写高效率的SQL。比如 SELECT * FROM TABEL 改为 SELECT field_1, field_2, field_3 FROM TABLE.
4. SQL注入的主要特点
变种极多,攻击简单,危害极大
sql注入的主要危害
未经授权操作数据库的数据
恶意纂改网页
私自添加系统账号或者是数据库使用者账号
网页挂木马
5.一条 SQL 语句在数据库框架中的执行流程
- 应用程序把查询 SQL 语句发送给服务器端执行;
- 查询缓存,如果查询缓存是打开的,服务器在接收到查询请求后,并不会直接去数据库查询,而是在数据库的查询缓存中找是否有相对应的查询数据,如果存在,则直接返回给客户端。只有缓存不存在时,才会进行下面的操作;
- 查询优化处理,生成执行计划。这个阶段主要包括解析 SQL、预处理、优化 SQL 执行计划;
- MySQL 根据相应的执行计划完成整个查询;
- 将查询结果返回给客户端。
6. 索引
(1)索引的分类
从数据结构角度
- 树索引 (O(log(n)))
- Hash 索引
从物理存储角度
- 聚集索引(clustered index)
- 非聚集索引(non-clustered index)
从逻辑角度
- 普通索引
- 唯一索引
- 主键索引
- 联合索引
- 全文索引
(2)索引的理解?
建立索引的原则:
- 在最频繁使用的、用以缩小查询范围的字段上建立索引;
- 在频繁使用的、需要排序的字段上建立索引。
不适合建立索引的情况:
- 对于查询中很少涉及的列或者重复值比较多的列,不宜建立索引;
- 对于一些特殊的数据类型,不宜建立索引,比如:文本字段(text)等。
(3)索引的底层使用的是什么数据结构?
- InnoDB 存储引擎:B+ 树
(4)使用索引的优缺点?
- 大大加快了数据的检索速度;
- 可以显著减少查询中分组和排序的时间;
- 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性;
- 将随机 I/O 变为顺序 I/O(B+Tree 索引是有序的,会将相邻的数据都存储在一起)
缺点:建立和维护索引耗费时间空间,更新索引很慢。
(5)哪些情况下索引会失效?
- 以“%(表示任意0个或多个字符)”开头的LIKE语句;
- OR语句前后没有同时使用索引;
- 数据类型出现隐式转化(如varchar不加单引号的话可能会自动转换为int型);
- 对于多列索引,必须满足 最左匹配原则/最左前缀原则 (最左优先,eg:多列索引col1、col2和col3,则 索引生效的情形包括 col1或col1,col2或col1,col2,col3);
- 如果MySQL估计全表扫描比索引快,则不使用索引(比如非常小的表)
(6)B+ 树的理解?
- B+ 树是基于 B 树和叶子节点顺序访问指针进行实现,它具有 B 树的平衡性,并且通过顺序访问指针来提高区间查询的性能。
- 进行查找操作时,首先在根节点进行二分查找,找到一个 key 所在的指针,然后递归地在指针所指向的节点进行查找。直到查找到叶子节点,然后在叶子节点上进行二分查找,找出 key 所对应的 data。
- 插入、删除操作会破坏平衡树的平衡性,因此在插入删除操作之后,需要对树进行一个分裂、合并、旋转等操作来维护平衡性。
B+Tree 的优势
B+树与B树的不同在于:
(1)所有值存储在叶子节点,非叶子节点不存储真正的data,而是作为索引
(2)为所有叶子节点增加了一个链指针 (可用作区间查询效率高)
索引是以索引文件的形式存在于硬盘中的,磁盘IO的消耗远远大于内存IO的消耗,若要根据索引的数据结构找数据时要尽量减少磁盘IO的次数。 磁盘并不是每次严格按需读取,而是每次都会预读。磁盘读取完需要的数据后,会按顺序再多读一部分数据到内存中。 (预读的原因: (1)当一个数据被用到时,其附近的数据也通常会马上被使用 (2)程序运行期间所需要的数据通常比较集中 ) 预读可以提高I/O效率.预读的长度一般为页(page)的整倍数 MySQL(默认使用InnoDB引擎),将记录按照页的方式进行管理,每页大小默认为16K 为什么mysql的索引使用B+树而不是B树呢?? (1)B+树更适合硬盘存储,由于非叶子节点不存储data,作为索引开销,所以一个节点可以存储更多的内节点,每个节点能索引的范围更大更精确。也就是说使用B+树单次磁盘IO的信息量相比较B树更大,IO效率更高。 (2)mysql是关系型数据库,经常会按照区间来访问某个索引列,B+树的叶子节点间按顺序建立了链指针,加强了区间访问性,所以B+树对索引列上的区间范围查询很友好。而B树每个节点的key和data在一起,无法进行区间查找。
(7)为什么 InnoDB 存储引擎选用 B+ 树而不是 B 树呢?
- IO次数少:B+树的中间结点只存放索引,数据都存在叶结点中,因此中间结点可以存更多的数据,让索引树更加矮胖;
- 范围查询效率更高:B树需要中序遍历整个树,只B+树需要遍历叶结点中的链表;
- 查询效率更加稳定:每次查询都需要从根结点到叶结点,路径长度相同,所以每次查询的效率都差不多
(8)哈希索引的理解?
哈希索引能以 O(1) 时间进行查找,但是失去了有序性。无法用于排序与分组、只支持精确查找,无法用于部分查找和范围查找。
InnoDB 存储引擎有一个特殊的功能叫“自适应哈希索引”,当某个索引值被使用的非常频繁时,会在 B+ 树索引之上再创建一个哈希索引,这样就让 B+Tree 索引具有哈希索引的一些优点,比如:快速的哈希查找。
(9) 怎么知道创建的索引有没有被使用到?
使用 Explain 命令来查看语句的执行计划,MySQL 在执行某个语句之前,会将该语句过一遍查询优化器,之后会拿到对语句的分析,也就是执行计划,其中包含了许多信息。可以通过其中和索引有关的信息来分析是否命中了索引,例如:possilbe_key、key、key_len 等字段,分别说明了此语句可能会使用的索引、实际使用的索引以及使用的索引长度。
7.主从复制
主从复制(Replication)是指数据可以从一个MySQL数据库主服务器复制到一个或多个从服务器,从服务器可以复制主服务器中的所有数据库或者特定的数据库,或者特定的表。默认采用异步模式。
实现原理:
- 主服务器 binary log dump 线程:将主服务器中的数据更改(增删改)日志写入 Binary log 中;
- 从服务器 I/O 线程:负责从主服务器读取binary log,并写入本地的 Relay log;
- 从服务器 SQL 线程:负责读取 Relay log,解析出主服务器已经执行的数据更改,并在从服务器中重新执行(Replay),保证主从数据的一致性
为什么要主从复制?
- 读写分离:主服务器负责写,从服务器负责读
- 缓解了锁的争用,即使主服务器中加了锁,依然可以进行读操作;
- 从服务器可以使用 MyISAM,提升查询性能以及节约系统开销;
- 增加冗余,提高可用性
- 数据实时备份,当系统中某个节点发生故障时,可以方便的故障切换
- 降低单个服务器磁盘I/O访问的频率,提高单个机器的I/O性能