一、MySQL 数据库与 SQL 优化

1、结构图

二、MySQL 数据库引擎简介

1、ISAM(IndexedSequentialAccessMethod)

    ISAM 是一个定义明确且历经时间考验的数据表格管理方法,它在设计之时就考虑到数据库被查询的次数要远大于更新的次数。因此,ISAM 执行读取操作的速度很快,而且不占用大量的内存和存储资源。 ISAM 的两个主要不足之处在于,它不支持事务处理,也不能够容错。 如果你的硬盘崩溃了,那么数据文件就无法恢复了。如果你正在把 ISAM 用在关键任务应用程序里,那就必须经常备份你所有的实时数据,通过其复制特性,MYSQL 能够支持 这样的备份应用程序。

注意:使用 ISAM 必须经常备份所有实时数据 。

2、MyISAM 存储引擎

    MyISAM 是 MySQL 的 ISAM 扩展格式(MySQL5.5 之前版本的缺省数据库引擎)数据库引擎。除了提供 ISAM 里所没有的索引和字段管理的大量功能,MyISAM 还使用一种表格锁定的机制,来优化多个并发的读写操作,其代价是你需要经常运行 OPTIMIZETABLE 命令, 来恢复被更新机制所浪费的空间。MyISAM 还有一些有用的扩展,例如用来修复数据库文件的 MyISAMCHK 工具和用来恢复浪费空间的 MyISAMPACK 工具。MYISAM 强调了快速读取操作,这可能就是为什么 MySQL 受到了 WEB 开发如此青睐的主要原因:在 WEB 开发中你所进行的大量数据操作都是读取操作。所以,大多数虚拟主机提供商和 INTERNET 平台提供商只允许使用 MYISAM 格式。 MyISAM 格式的一个重要缺陷就是不能在表损坏后恢复数据 。

注意:必须经常使用 OptimizeTable 命令清理空间;必须经常备份所有实时数据。工具有用来修复数据库文件的 MyISAMCHK 工具和用来恢复浪费空间的 MyISAMPACK 工具。不支持事务。数据越多,写操作效率越低。 因为要维护数据和索引信息。(索引列越多,相对效率越低)。

使用该引擎,会生成三个文件:

  • .frm:表结构信息
  • .MYD:数据文件
  • .MYI:表的索引信息
3、InnoDB 存储引擎

    InnoDB 给 MySQL 提供了具有提交、回滚和崩溃恢复能力的事务安全(ACID 兼容)存储引擎。InnoDB 锁定在行级并且也在 SELECT 语句提供一个 Oracle 风格一致的非锁定读,这些特色增加了多用户部署的性能。没有在 InnoDB 中扩大锁定的需要,因为在 InnoDB 中行级锁定适合非常小的空间。 InnoDB 也支持 FOREIGNKEY 强制。在 SQL 查询中,你可以自由地将 InnoDB 类型的表与其它 MySQL 的表的类型混合起来,甚至在同一个查询中也可以混合。

    InnoDB 是为处理巨大数据量时的最大性能设计,它的 CPU 效率可能是任何其它基于磁盘的关系数据库引擎所不能匹敌的。

    InnoDB 存储引擎被完全与 MySQL 服务器整合, InnoDB 存储引擎为在主内存中缓存数据和索引而维持它自己的缓冲池。InnoDB 存储它的表&索引在一个表空间中,表空间可以包含数个文件(或原始磁盘分区)。这与 MyISAM 表不同,比如在 MyISAM 表中每个表被存在分离的文件中。InnoDB 表可以是任何尺寸,即使在文件尺寸被限制为 2GB 的操作系统上。

    在 MySQL5.7 版本中,InnoDB 存储引擎管理的数据文件为两个:分别是 .frm、.idb 文件。

InnoDB特点:

  1. 支持事务。
  2. 数据多版本读取(InnoDB+MyISAM+ISAM)。
  3. 锁定机制的改进。
  4. 实现外键。

InnoDB 与 MyISAM 区别:

  1. InnoDB 支持事务,MyISAM 不支持,对于 InnoDB 每一条 SQL 语言都默认封装成事务, 自动提交,这样会影响速度,所以最好把多条 SQL 语言放在 begin transaction 和 commit 之间,组成一个事务。
  2. InnoDB 支持外键,而 MyISAM 不支持。对一个包含外键的 InnoDB 表转为 MYISAM 会失败。
  3. InnoDB 是聚集索引,数据文件是和索引绑在一起的,必须要有主键,通过主键索引效率很高。但是辅助索引需要两次查询,先查询到主键,然后再通过主键查询到数据。因此, 主键不应该过大,因为主键太大,其他索引也都会很大。而 MyISAM 是非聚集索引,数据文件是分离的,索引保存的是数据文件的指针。主键索引和辅助索引是独立的。
  4. InnoDB 不保存表的具体行数,执行 select count(*) from table 时需要全表扫描。而 MyISAM 用一个变量保存了整个表的行数,执行上述语句时只需要读出该变量即可,速度很快。
  5. InnoDB 不支持全文索引,而 MyISAM 支持全文索引,MyISAM 查询效率要高。

使用InnoDB与MyISAM分析:

  1. 是否要支持事务,如果要请选择 innodb,如果不需要可以考虑 MyISAM
  2. 如果表中绝大多数都只是读查询,可以考虑 MyISAM,如果既有读写也挺频繁,请使用 InnoDB。
  3. 系统崩溃后,MyISAM 恢复起来更困难,能否接受。
  4. MySQL5.5 版本开始 Innodb 已经成为 Mysql 的默认引擎(之前是 MyISAM),说明其优势是有目共睹的,如果你不知道用什么,那就用 InnoDB,至少不会差。
4、Memory 存储引擎

    Memory 存储引擎,是一个将数据存储在内存中的存储引擎。Memory 存储引擎不会将任何数据存放到磁盘上,仅仅存放了一个表结构相关信息的 .frm 文件在磁盘上面。所以一旦 MySQL Crash 或者主机 Crash 之后,Memory 的表就只剩下一个结构了。Memory 表支持索引,并且同时支持 Hash 和 B-Tree 两种格式的索引。由于是存放在内存中,所以 Memory 都是按照定长的空间来存储数据的,而且不支持 BLOB 和 TEXT 类型的字段。Memory 存储引擎实现页级锁定。

5、NDBCluster 存储引擎

    NDB存储引擎也叫 NDBCluster 存储引擎,主要用于 MySQLCluster 分布式集群环境,Cluster 是 MySQL 从5.0版本才开始提供的新功能。

6、FEDERATED 存储引擎

    FEDERATED 存储引擎所实现的功能,和 Oracle 的 DBLINK 基本相似,主要用来提供对远程 MySQL 服务器上面的数据的访问接口。如果我们使用源码编译来安装 MySQL,那么必须手工指定启用 FEDERATED 存储引擎才行,因为 MySQL 默认是不起用该存储引擎的。

7、ARCHIVE 存储引擎

    ARCHIVE 存储引擎主要用于通过较小的存储空间来存放过期的很少访问的历史数据。ARCHIVE表不支持索引,通过一个 .frm 的结构定义文件,一 个 .ARZ 的数据压缩文件还有一个 .ARM 的 meta 信息文件。由于其所存放的数据的特殊性,ARCHIVE 表不支持删除,修改操作,仅支持插入和查询操作。锁定机制为行级锁定。

8、BLACKHOLE 存储引擎

    BLACKHOLE 存储引擎是一个非常有意思的存储引擎,功能恰如其名,就是一个“黑洞”。就像我 们 unix 系统下面的“/dev/null”设备一样,不管我们写入任何信息,都是有去无回。

9、CSV 存储引擎

    CSV 存储引擎实际上操作的就是一个标准的 CSV 文件 ,他不支持索引。其主要用途就是大家有些时候可能会需要通过数据库中的数据导出成一份报表文件,而 CSV 文件是很多软件都支持的一种较为标准的格式,所以我们可以通过先在数据库中建立一张 CSV 表,然后将生成的报表信息插入到该表,即可得到一份 CSV 报表文件了。

三、存储引擎管理

1、查看数据库支持的存储引擎
show engines;
2、查看数据库当前使用的存储引擎
# 查看默认引擎
show variables like'%storage_engine%';
# 也可以在 MySQL 配置文件中查看。windows - my.ini文件  &&  linux - my.cnf文件
3、查看数据库表所用的存储引擎
show create table 表名;
4、创建表指定存储引擎
create table table_name(column_namecolumn_type
)ENGINE=存储引擎名 DEFAULT CHARSET=UTF8;
5、修改表的存储引擎
alter table 表名 engine=存储引擎名
6、修改默认的存储引擎

在 windows 系统中 mysql 安装目录中的 my.ini 配置文件中修改;在 Linux 系统中 /etc/my.cnf 文件中。

default-storage-engine=INNODB

四、MySQL 中的索引

1、索引的优点

作用: 索引大大提高了系统的查询性能。

  1. 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。
  2. 可以大大加快数据的检索速度,这也是创建索引的最主要的原因。
  3. 可以加速表和表之间的连接,特别是在实现数据的参考完整性方面特别有意义。
  4. 在使用分组和排序子句进行数据检索时,同样可以显著减少查询中分组和排序的时间。
  5. 通过使用索引,可以在查询的过程中,使用查询优化器,提高系统的性能。
2、索引的缺点
  1. 创建索引和维护索引要耗费时间,这种时间随着数据量的增加而增加。
  2. 索引需要占物理空间,除了数据表占数据空间之外,每一个索引还要占一定的物理空间。如果要建立聚簇索引,那么需要的空间就会更大。
  3. 当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,这样就降低了数据的维护速度。
3、什么样的字段适合创建索引

    索引是建立在数据库表中的某些列的上面。因此,在创建索引的时候,应该仔细考虑在哪些列上可以创建索引,在哪些列上不能创建索引。 一般来说,应该在具备下述特性的列上创建索引:

  1. 在经常需要搜索的列上,可以加快搜索的速度。
  2. 在作为主键的列上,强制该列的唯一性和组织表中数据的排列结构。
  3. 在经常用在连接的列上,这些列主要是一些外键,可以加快连接的速度。
  4. 在经常需要根据范围进行搜索的列上创建索引,因为索引已经排序,其指定的范围是连续的。
  5. 在经常需要排序的列上创建索引,因为索引已经排序,这样查询可以利用索引的排序,加快排序查询时间。
  6. 在经常使用在 WHERE 子句中的列上面创建索引,加快条件的判断速度。

    建立索引,一般按照 select 的 where 条件来建立,比如: select 的条件是 where f1 and f2,那么如果我们在字段 f1 或字段 f2 上建立索引是没有用的,只有在字段 f1 和 f2 上同时建立索引才有用的。

4、什么样的字段不适合创建索引
  1. 对于那些在查询中很少使用或者参考的列不应该创建索引。这是因为,既然这些列很少使用到,因此有索引或者无索引,并不能提高查询速度。相反,由于增加了索引,反 而降低了系统的维护速度和增大了空间需求。
  2. 对于那些只有很少数据值的列也不应该增加索引。这是因为,由于这些列的取值很少,例如人事表的性别列,在查询的结果中,结果集的数据行占了表中数据行的很大比例,即需要在表中搜索的数据行的比例很大。增加索引,并不能明显加快检索速度。
  3. 对于那些定义为 text,image 和 bit 数据类型的列不应该增加索引。这是因为,这些列的数据量要么相当大,要么取值很少。
  4. 当修改性能远远大于检索性能时,不应该创建索引。这是因为,修改性能和检索性能是互相矛盾的。当增加索引时,会提高检索性能,但是会降低修改性能。当减少索引时,会提高修改性能,降低检索性能。因此,当修改性能远远大于检索性能时,不应该创建索引。

五、MySQL 中的索引种类

1、B-Tree 索引

    B-Tree 索引,顾名思义,就是所有的索引节点都按照平衡二叉树(balance tree) 的数据结构来存储。 B-tree 结构可以显著减少定位记录时所经历的中间过程,从而加快存取速度。

B-tree中,每个节点包括:

  1. 本结点所含关键字的个数。
  2. 指向父节点的指针。
  3. 关键字。
  4. 指向子节点的指针。

    对于一棵 m 阶 B-tree,每个结点至多可以拥有 m 个子结点。各结点的关键字和可以拥有的子结点数都有限制,规定 m 阶 B-tree 中,根结点至少有 2 个子结点,除非根结点为叶子节点,相应的,根结点中关键字的个数为 1 ~ m-1;非根结点至少有[m/2]([],向上取整)个子结点,相应的,关键字个数为[m/2]-1 ~ m-1。

B-tree的特征:

  1. 关键字集合分布在整棵树中。
  2. 任何一个关键字出现且只出现在一个结点中。
  3. 搜索有可能在非叶子结点结束。
  4. 其搜索性能等价于在关键字全集内做一次二分查找。
  5. 自动层次控制。

由于限制了除根结点以外的非叶子结点,至少含有 M/2 个儿子,确保了结点的至少利用率,其最低搜索性能为:

其中,M 为设定的非叶子结点最多子树个数,N 为关键字总数;所以B-tree的性能总是等价于二分查找(与 M 值无关),也就没有B树平衡的问题;由于 M/2 的限制,在插入的结点时,如果结点已满,需要将结点分裂为两个各占 M/2 的结点;删除结点时,需要将两个不足 M/2 的兄弟结点合并。

2、Full-text 全文索引

    Full-text 索引就是我们常说的全文索引,他的存储结构也是 b-tree。主要是为了解决在我们需要用 like 查询的低效问题。只能解决’xxx%’的 like 查询。如:字段数据为 ABCDE,索引建立为-A、AB、ABC、ABCD、ABCDE 五个。

六、MySQL 中的索引管理

    在 MySQL 中,对索引的查看和删除操作是所有索引类型通用的。

1、创建索引的方法

建表时创建索引格式:

create table 表名(字段名 数据类型 [完整性约束条件],.....,[UNIQUE | FULLTEXT | SPATIAL] INDEX | KEY[索引名](字段名1 [(长度)][ASC | DESC]) [USING 索引方法]
);

说明:

UNIQUE:可选,表示索引为唯一性索引。

FULLTEXT:可选,表示索引为全文索引。

SPATIAL:可选,表示索引为空间索引。

INDEX 和 KEY:用于指定字段为索引,两者选择其中之一就可以了,作用是一样的。

索引名:可选,给创建的索引取一个新名称。

字段名1:指定索引对应的字段的名称,该字段必须是建表时定义好的字段。

长度:可选,指索引的长度,必须是字符串类型才可以使用。

ASC:可选,表示升序排列。

DESC:可选,表示降序排列。

注:索引方法默认使用B+TREE。

示例:

CREATE TABLE projectfile (id INT AUTO_INCREMENT COMMENT '附件id',fileuploadercode VARCHAR(128) COMMENT '附件上传者code',projectid INT COMMENT '项目id;此列受project表中的id列约束',filename VARCHAR (512) COMMENT '附件名',fileurl VARCHAR (512) COMMENT '附件下载地址',filesize BIGINT COMMENT '附件大小,单位Byte',-- 主键本身也是一种索引(注:也可以在上面的创建字段时使该字段主键自增)PRIMARY KEY (id),-- 主外键约束(注:project表中的id字段约束了此表中的projectid字段)FOREIGN KEY (projectid) REFERENCES project (id),-- 给projectid字段创建了唯一索引(注:也可以在上面的创建字段时使用unique来创建唯一索引)UNIQUE INDEX (projectid),-- 给fileuploadercode字段创建普通索引INDEX (fileuploadercode)-- 指定使用INNODB存储引擎(该引擎支持事务)、utf8字符编码
) ENGINE = INNODB DEFAULT CHARSET = utf8 COMMENT '项目附件表';

建表后再创建索引格式:

-- 方法一:
ALTER TABLE 表名 ADD [UNIQUE | FULLTEXT | SPATIAL] INDEX | KEY [索引名] (字段名1 [(长度)] [ASC | DESC]) [USING 索引方法];
-- 方法二:
CREATE [UNIQUE | FULLTEXT | SPATIAL] INDEX 索引名 ON 表名(字段名) [USING 索引方法];

示例一:

-- 假设建表时fileuploadercode字段没创建索引(注:同一个字段可以创建多个索引,但一般情况下意义不大)
-- 给projectfile表中的fileuploadercode创建索引
ALTER TABLE projectfile ADD UNIQUE INDEX index_name (fileuploadercode);

示例二:

-- 组合索引
ALTER TABLE projectfile ADD INDEX index_name (fileuploadercode, projectid);
-- 方式二创建索引
CREATE INDEX index_name ON projectfile(fileuploadercode(3))

示例三:

-- 将id列设置为主键
ALTER TABLE index_demo ADD PRIMARY KEY(id) ;
-- 将id列设置为自增
ALTER TABLE index_demo MODIFY id INT auto_increment;
2、查看索引
SHOW INDEX FROM [table_name];
--  只在 MySQL 中可以使用 keys 关键字。
SHOW KEYS FROM [table_name];
3、删除索引
DROP INDEX [index_name] ON [table_name];
ALTER TABLE [table_name] DROP INDEX [index_name];
ALTER TABLE [table_name] DROP PRIMARY KEY;
4、普通索引

    这是最基本的索引,它没有任何限制 MyIASM 中默认的 B-tree 类型的索引,也是我们大多数情况下用到的索引。

示例:

-- 方式一:
CREATE INDEX index_name ON table_name(column(length))
-- 方式二:
ALTER TABLE table_name ADD INDEX index_name(column(length))
-- 方式三:
CREATE TABLE table_name (id int not null auto_increment,title varchar(30),PRIMARY KEY(id),INDEX index_name(title(5))
);
5、唯一索引

    与普通索引类似,不同的就是:索引列的值必须唯一,但允许有空值(注意和主键不同)。如果是组合索引,则列值的组合必须唯一,创建方法和普通索引类似。

示例:

-- 方式一:
CREATE UNIQUE INDEX index_name ON table_name(column(length))
-- 方式二:
ALTER TABLE table_name ADD UNIQUE INDEX index_name(column(length))
-- 方式三:
CREATE TABLE table_name (id int not null auto_increment,title varchar(30),PRIMARY KEY(id),UNIQUE INDEX index_name(title(5))
);
6、全文索引(FULLTEXT)

    MySQL 从 3.23.23 版开始支持全文索引和全文检索,FULLTEXT索引仅可用于 MyISAM 表; 他们可以从 CHAR、VARCHAR 或 TEXT 列 中作为 CREATE TABLE 语句的一部分被创建,或是随后使用 ALTER TABLE 或 CREATE INDEX 被添加。

    对于较大的数据集,将你的资料输入一个没有 FULLTEXT 索引的表中,然后创建索引,其速度比把资料输入现有 FULLTEXT 索引的速度更为快。不过切记对于大容量的数据表,生成全文索引是一个非常消耗时间非常消耗硬盘空间的做法。

示例:

-- 方式一:
CREATE FULLTEXT INDEX index_name ON table_name(column(length))
-- 方式二:
ALTER TABLE table_name ADD FULLTEXT INDEX index_name(column(length))
-- 方式三:
CREATE TABLE table_name (id int not null auto_increment,title varchar(30),PRIMARY KEY(id),FULLTEXT INDEX index_name(title(5))
);
7、组合索引(最左原则)
CREATE TABLE article(id int not null,title varchar(255),time date
)

    平时用的 SQL 查询语句一般都有比较多的限制条件,所以为了进一步榨取 MySQL 的效率,就要考虑建立组合索引。例如上表中针对 title 和 time 建立一个组合索引:

ALTER TABLE article ADD INDEX index_title_data(title(50),time(10))

建立这样的组合索引,其实是相当于分别建立了下面两组组合索引:

-title,time
-title

    为什么没有 time 这样的组合索引呢?这是因为 MySQL 组合索引“最左前缀”的结果。简单的理解就是只从最左面的开始组合。并不是只要包含这两列的查询都会用到该组合索引, 如下面的几个 SQL 所示:

-- 使用到上面的索引
SELECT * FROM artice WHERE title='测试' AND time=123456789;
SELECT * FROM artice WHERE title='测试';
-- 不使用上面的索引
SELECT * FROM artice WHERE time=123456789;

七、MySQL 中的索引优化

1、概述

    上面都在说使用索引的好处,但过多的使用索引将会造成滥用。因此索引也会有它的缺点。虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行 INSERT、 UPDATE 和 DELETE 次数大于查询次数时,放弃索引。因为更新表时,MySQL 不仅要保存数据,还要保存一下索引文件。建立索引会占用磁盘空间的索引文件。一般情况这个问题不太严重,但如果你在一个大表上创建了多种组合索引,索引文件的会膨胀很快。索引只是提高效率的一个因素,如果你的 MySQL 有大数据量的表,就需要花时间研究建立最优秀的索引,或优化查询语句。

2、索引不会包含有 NULL 列的值

    只要列中包含有 NULL 值都将不会被包含在索引中,组合索引中只要有一列含有 NULL 值,那么这一列对于此组合索引就是无效的。所以我们在数据库设计时不要让字段的默认值为 NULL。

CREATE TABLE table_name(c1 varchar(32) DEFAULT '0'
);
3、使用短索引

    对串列进行索引,如果可能应该指定一个前缀长度。例如,如果有一个 CHAR(255) 的列,如果在前 10 个或 20 个字符内,多数值是惟一的,那么就不要对整个列进行索引。短索引不仅可以提高查询速度而且可以节省磁盘空间和 I/O 操作。

CREATE INDEX index_name ON table_name(column(length))
4、索引列排序

    MySQL 查询只使用一个索引,因此如果 where 子句中已经使用了索引的话,那么 order by 中的列是不会使用索引的。因此数据库默认排序可以符合要求的情况下不要使用排序操作;尽量不要包含多个列的排序,如果需要最好给这些列创建复合索引。

5、like语句操作

    一般情况下不鼓励使用 like 操作,如果非使用不可,如何使用也是一个问题。 like "%aaa%"不会使用索引,而 like "aaa%"可以使用索引。

6、不要在列上进行运算

示例:

select * from users where YEAR(adddate) < 2007

将在每个行上进行运算,这将导致索引失效而进行全表扫描,因此我们可以改成:

select * from users where adddate < '2007-01-01'

八、索引总结

    MySQL 只对以下操作符才使用索引:<,<=,=,>,>=,between,in,以及某些时候的 like(不以通配符 % 或 _ 开头的情形)。而理论上每张表里面最多可创建 16 个索引,不过除 非是数据量真的很多,否则过多的使用索引也不是那么好玩的。

建议: 一个表的索引数最好不要超过 6 个,若太多则应考虑一些不常使用到的列上建的索引是否有必要。

九、MySQL 中的 SQL 的常见优化策略

1、避免全表扫描

    对查询进行优化,应尽量避免全表扫描,首先应考虑在 whereorder by 涉及的列上建立索引。

2、避免判断 null 值

    应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描

示例:

select id from users where num is null;
-- 可以在 num 上设置默认值 0,确保表中 num 列没有 null 值,然后这样查询:
select id from users where num=0;
3、避免不等值判断

    应尽量避免在 where 子句中使用 !=<> 操作符,否则引擎将放弃使用索引而进行全表扫描。

4、避免使用 or 逻辑

    应尽量避免在 where 子句中使用 or 来连接条件,否则将导致引擎放弃使用索引而进行全表扫描。

示例:

select id from users where num = 10 or num = 20;
-- 可以这样查询:
select id from users where num = 10
union all
select id from users where num = 20
5、慎用 in 和 not in 逻辑

    innot in 也要慎用,否则会导致全表扫描。

示例:

select id from users where num in(select id from info where id>10);
-- 此时外层查询会全表扫描,不使用索引,可修改为:
select id from users,(select id from info where id>10) as t where users.id=t.id;
-- 此时索引被使用,可以明显提升查询效率
6、注意模糊查询

下面查询将导致全表扫描:

select id from users where name like'%张%';

模糊查询如果是必要条件时,可以使用

select id from users where name like'张%';

来实现模糊查询,此时索引将被使用。如果头匹配是必要逻辑,建议使用全文搜索引擎(Elasticsearch、 Lucene、Solr 等)。

7、避免查询条件中字段计算

    应尽量避免在 where 子句中 对字段进行表达式操作 ,这将导致引擎放弃使用索引而进行全表扫描。

示例:

select id from users where num/2 = 50;
-- 应改为
select id from users where num = 100/2;
8、避免查询条件中对字段进行函数操作

    应尽量避免在 where 子句中对 字段进行函数操作 ,这将导致引擎放弃使用索引而进行全表扫描。

示例:

-- 查询 name 以上官开头的 id
-- substring函数:从字符串下标从1开始截取字符串
select id from users where substring(name,1,2) = '上官'
-- 应优化为
select id from users where name like'上官%';
9、WHERE 子句 “=” 左边注意点

    不要在 where 子句中的 "=" 左边进行函数、算术运算或其他表达式运算,否则系统将可能无法正确使用索引。

10、组合索引使用

    在使用索引字段作为条件时,如果该索引是复合索引,那么必须使用到该索引中的第一个字段作为条件时才能保证系统使用该索引,否则该索引将不会被使用,并且应尽可能的让字段顺序与索引顺序相一致。

11、不要定义无意义的查询

不要写一些没有意义的查询,如需要生成一个空表结构:

select * into new_table_name from old_table_name where 1=0

这类代码不会返回任何结果集,但是会消耗系统资源的,应改成这样

create table new_table_name(select * from old_table_name);
12、exists

使用 exists 代替 in 是一个很好的选择:

select num from users where num in(select num from info);
-- 应优化为
select num from users where exists(select 1 from info where num=users.num);
13、索引也可能失效

    并不是所有索引对查询都有效,SQL 是根据表中数据来进行查询优化的,当索引列有大量数据重复时,SQL查询可能不会去利用索引,如一表中有字段 sex,male、female 几乎各一半,那么即使在 sex 上建了索引也对查询效率起不了作用。

14、表格字段类型选择

    尽量使用数字型字段,若只含数值信息的字段尽量不要设计为字符型,这会降低查询和连接的性能,并会增加存储开销。这是因为引擎在处理查询和连接时会逐个比较字符串中每 一个字符,而对于数字型而言只需要比较一次就够了。

    尽可能的使用 varchar 代替 char ,因为首先可变长度字段存储空间小,可以节省存储空间,其次对于查询来说,在一个相对较小的字段内搜索效率显然要高些。

15、查询语法中的字段

    任何地方都不要使用 select \* from users,用具体的字段列表代替 "*",不要返回用不到的任何字段。

16、索引无关优化
  1. 不使用*、尽量不使用 union,union all 等关键字、尽量不使用 or 关键字、尽量使用等值判断。
  2. 表连接建议不超过 5 个。如果超过 5 个,则考虑表格的设计。(互联网应用中)
  3. 表连接方式使用外联优于内联。
  4. 外连接有基础数据存在。如:A left join B ,基础数据是 A。
  5. A inner join B,没有基础数据的,先使用笛卡尔积完成全连接,在根据连接条件得到内连接结果集。
  6. 大数据量级的表格做分页查询时,如果页码数量过大,则使用子查询配合完成分页逻辑。
select * from table limit 1000000,10
select * from table where id in(select pk from table limit 100000,10)

MySQL数据库与SQL优化相关推荐

  1. MySQL数据库:SQL优化与索引优化

    一.索引优化: 1.like语句的前导模糊查询不使用索引: select * from doc where title like '%XX':   --不能使用索引 select * from doc ...

  2. mysql 判断字段为null表示 false 其它为true_日拱一卒,MySQL数据库 常用SQL优化技巧 十一式...

    本文中所提到的SQL优化技巧均是基于Mysql 索引 BTree类型 .将从以下几个方面介绍常用的SQL优化技巧: 避免在 WHERE 子句中使用 != 或 <> 操作符. 避免在 WHE ...

  3. 千万级的mysql数据库与sql优化方法

    http://www.111cn.net/database/110/32932.htm 对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2.应 ...

  4. 高并发大流量专题---10、MySQL数据库层的优化

    高并发大流量专题---10.MySQL数据库层的优化 一.总结 一句话总结: mysql先考虑做分布式缓存,过了缓存后就做mysql数据库层面的优化 1.mysql数据库层的优化的前面一层是什么? 数 ...

  5. MySQL数据库如何做好优化

    MySQL数据库如何做好优化 (碰到过好几次这样的题目,可每次都不能答的完全正确,现在大概列出如下:(望各位补充) (1.数据库的设计 ((尽量把数据库设计的更小的占磁盘空间. (1).尽可能使用更小 ...

  6. MySQL进阶之SQL优化

    1.使用 show status like 'Com%';可以查到各种语句执行的次数. Com_select:执行select操作的次数. Com_insert:执行insert的次数 Com_upd ...

  7. 读《深入浅出MySQL数据库开发、优化与管理维护(第2版)》笔记2 WITH ROLLUP关键字

    读<深入浅出MySQL数据库开发.优化与管理维护(第2版)>笔记2 WITH ROLLUP关键字 WITH ROLLUP是可选语法,表名是否对分类聚合后的结果进行再汇总; 我自己的使用实例 ...

  8. Mysql数据库以及sql语言

    mysql 安装请点击 mysql下载速度慢请点击 可视化工具请点击(不想用命令行的) mysql和java集成:jdbc mysql 索引的创建以及含义 mysql一般函数的使用(需要一定的sql基 ...

  9. atitit.跨语言实现备份mysql数据库 为sql文件特性 api 兼容性java c#.net php js

    atitit.跨语言实现备份mysql数据库 为sql文件特性 api 兼容性java c#.net php js 1. 两个方法:: bat vs mysqldump(推荐)  vs   lang  ...

最新文章

  1. http协议报文体_HTTP协议详解
  2. php adodb smarty,smarty+adodb+部分自定义类的php开发模式
  3. python global用法_【python测试开发栈】python基础语法大盘点
  4. Ubuntu16.04 设置环境变量的方法
  5. 《重来》值得你多看几遍
  6. 实践SaltStack安装和配置管理
  7. hdu 4640 Island and study-sister(状态压缩dp)
  8. RS232 RS422 RS485通讯原理
  9. 计算机装系统常用单词,电脑bios中英文对照表大全,安装系统再也不怕英文了...
  10. 想要买房的人究竟有多可悲?! --水木周平
  11. [2022 强网杯] devnull 复现
  12. 阿里代运营一定要掌握的几大技能!
  13. 重新认识 Java 的 System.in
  14. linux系统可以玩星际争霸吧,暴雪携手DeepMind推出《星际争霸2》API工具,玩家可以“调教”AI打游戏了...
  15. 2018届春招面试回顾(一)
  16. 肠道菌群检测在临床感染判别中的应用
  17. 6个思维导图工具精通一款让你的效率大大提升,快他不止一步!
  18. 打印机控制 佳博 Gprinter GP-9134T
  19. 苹果cms v10版本整合ckplayer播放器
  20. 孙祥:尊重别人是尊重自己 大牌印象最深是苏克

热门文章

  1. 从《大数据日知录》的目录想到的学习路径
  2. 数据结构学习-循环链表:处理约瑟夫环问题
  3. 在Vmware中优化苹果虚拟机
  4. linux下geany配置python_Linux系统下搭建基于Geany+Python开发环境
  5. 二维方格子Ising模型代码
  6. 微软在线预览文档链接
  7. 人工智能基础 | Python实现 洗衣机模糊推理系统
  8. pngquant php,如何在PHP中使用pngquant
  9. 虚拟机创建共享文件夹
  10. 工控安全工业网络病毒的防范与治理