MySQL与SQL优化

MySQL DBMS-MySQL Database Management System。数据库管理系统。

1. 结构图

在这里插入图片描述

2. MySQL数据库引擎简介
2.1 ISAM(Indexed Sequential Access Method)

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

2.2 MyISAM

MyISAM是MySQL的ISAM扩展格式(MySQL5.5之前版本的缺省数据库引擎)数据库引擎。除了提供ISAM里所没有的索引和字段管理的大量功能,MyISAM还使用一种表格锁定的机制,来优化多个并发的读写操作,其代价是你需要经常运行optimizetable命令,来恢复被更新机制所浪费的空间。MyISAM还有一些有用的扩展,例如用来修复数据库文件的MyISAMCHK工具和用来恢复浪费空间的MyISAMPACK工具。MyISAM强调了快速读取操作,这可能就是为什么MySQL受到了WEB开发如此青睐的主要原因:在WEB开发中你所进行的大量数据操作都是读取操作。所以,大多数虚拟主机提供商和INTERNET平台提供商只允许使用MyISAM格式。MyISAM格式的一个重要缺陷就是不能在表损坏后恢复数据。(也不支持事务)
MyISAM引擎使用注意:必须经常使用OptimizeTable命令清理空间;必须经常备份所有实时数据。工具有用来修复数据库文件的MyISAMCHK工具和用来恢复浪费弓箭的MyISAMPACK工具。不支持事务。数据越多,写操作效率越低。因为要维护数据和索引信息。(因为要维护数据和索引信息,索引越多,相对效率越低)
使用该数据库引擎,会生成三个文件:

  • .frm:表结构信息
  • .MYD:数据文件
  • .MYl:表的索引信息
2.3 InnoDB

InnoDB数据库引擎就是造就MySQL灵活性的技术的直接产品,这项技术就是MySQL++ API,在使用MySQL的时候,你所面对的每一个挑战几乎都源于ISAM和MyISAM数据库引擎不支持事务处理(transaction process)也不支持外键。尽管要比ISAM和MyISAM引擎慢很多,但是InnoDB包括了对事物和外键的支持,这两点都是前两个引擎所没有的。现在的MySQL(5.5以上 版本)常用版本默认存储引擎MySQL官方对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特点:

  • 支持事务
  • 数据多版本读取(InnoDB+MyISAM+ISAM)
  • 锁定机制的改进
  • 实现外键
2.3.1 InnoDB与MyISAM区别

1、InnnoDB支持事务,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要高。

2.3.2 如何选择

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

2.4 Memory存储引擎

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

2.5 NDBCluster

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

2.6Merge存储引擎

Merge存储引擎,在MySQL用户手册中也提到了,也被认识为MRG_MyISAM引擎。Merge存储引擎可以简单的理解为其功能就是实现了对结构相同的MyISAM表,通过一些特殊的包装对外提供一个单一的访问入口,以达到减小应用的复杂度的目的。要创建Merge表,不仅仅基表的结构要完全一致,包括字段的顺序,基表的索引也必须完全一致。BDB存储引擎全称为BerkeleyDB存储引擎,和InnoDB一样,也不是MySQL自己开发实现的一个存储引擎,而是由SleepycatSoftware所提供,当然,也是开源存储引擎,同样支持事务安全。

2.7 Federated

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

2.8 Archive

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

2.9 BlackHole

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

2.10 CSV

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

3. 存储引擎管理
3.1 查看数据库支持的存储引擎
mysql> show engines;
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
| Engine             | Support | Comment                                                        | Transactions | XA   | Savepoints |
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
| FEDERATED          | NO      | Federated MySQL storage engine                                 | NULL         | NULL | NULL       |
| MRG_MYISAM         | YES     | Collection of identical MyISAM tables                          | NO           | NO   | NO         |
| MyISAM             | YES     | MyISAM storage engine                                          | NO           | NO   | NO         |
| BLACKHOLE          | YES     | /dev/null storage engine (anything you write to it disappears) | NO           | NO   | NO         |
| CSV                | YES     | CSV storage engine                                             | NO           | NO   | NO         |
| MEMORY             | YES     | Hash based, stored in memory, useful for temporary tables      | NO           | NO   | NO         |
| ARCHIVE            | YES     | Archive storage engine                                         | NO           | NO   | NO         |
| InnoDB             | DEFAULT | Supports transactions, row-level locking, and foreign keys     | YES          | YES  | YES        |
| PERFORMANCE_SCHEMA | YES     | Performance Schema                                             | NO           | NO   | NO         |
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+

3.2 查看数据库当前使用的存储引擎
mysql> show variables like '%storage_engine%';
+------------------------+--------+
| Variable_name          | Value  |
+------------------------+--------+
| default_storage_engine | InnoDB |
| storage_engine         | InnoDB |
+------------------------+--------+

也可以在MySQL配置文件中查看:

  • windows -my.ini
  • linux -my.cnf
3.3 查看数据库表所用的存储引擎
mysql> show create table t_user;
+--------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table  | Create Table                                                                                                                                                                                                              |
+--------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| t_user | CREATE TABLE `t_user` (
  `uid` int(11) NOT NULL AUTO_INCREMENT,
  `uname` varchar(255) DEFAULT NULL,
  `password` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`uid`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8 |
+--------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

3.4 创建表指定存储引擎

create table table_name (column_name column_type) engine = engine_name

mysql> create table t_temp (id int(11) primary key,name varchar(255)) engine=myisam;
Query OK, 0 rows affected (0.07 sec)

mysql> show create table t_temp;
+--------+------------------------------------------------------------------------------------------------------------------------------------------------+
| Table  | Create Table                                                                                                                                   |
+--------+------------------------------------------------------------------------------------------------------------------------------------------------+
| t_temp | CREATE TABLE `t_temp` (
  `id` int(11) NOT NULL,
  `name` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 |
+--------+------------------------------------------------------------------------------------------------------------------------------------------------+

3.5 修改表的存储引擎

alter table table_name engine = engine_name

mysql> alter table t_temp engine = innodb;
Query OK, 0 rows affected (0.11 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> show create table t_temp;
+--------+------------------------------------------------------------------------------------------------------------------------------------------------+
| Table  | Create Table                                                                                                                                   |
+--------+------------------------------------------------------------------------------------------------------------------------------------------------+
| t_temp | CREATE TABLE `t_temp` (
  `id` int(11) NOT NULL,
  `name` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
+--------+------------------------------------------------------------------------------------------------------------------------------------------------+

3.6 修改默认的存储引擎

在MySQL配置文件中修改下述内容:
defaul-storage-engine=INNODB
MySQL配置文件:

  • windows系统 MySQL安装目录/my.ini(5.7版本my.ini文件在数据目录中)。
  • linux系统 /etc/my.cnf
    重启MySQL数据库
4. MySQL中的索引简介
4.1 索引的优点

为什么要创建索引?这是因为,创建索引可以大大提高系统的查询性能。

  • 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。
  • 可以大大加快数据的检索速度,这也是创建索引的最主要原因。
  • 可以加速表和表之间的连接,特别是在实现数据库的参考完整性方面特别有意义。
  • 在使用分组和排序字句进行数据检索时,同样可以显著减少查询中分组和排序的时间。
  • 通过使用索引,可以在查询的过程中,使用查询优化器,提高系统的性能。
4.2 索引的缺点

索引虽然有诸多优点,但是为表中的每一列都增加索引,是非常不明智的。这是因为,增加索引也有许多不利的一个方面:

  • 创建索引和维护索引要耗费时间,这种时间随着数据量的增加而增加。
  • 索引需要占物理空间,除了数据表占数据空间之外,每一个索引还要占一定的物理空间。如果要建立聚簇索引,那么需要的空间就会更大。
  • 当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,这样就降低了数据的维护速度。
4.3 什么样的字段适合创建索引

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

  • 在经常需要搜索的列上,可以加快搜索的速度。
  • 在作为主键的列上,强制该列的唯一性和组织表中数据的排列结构。
  • 在经常用在连接的列上,这些列主要是一些外键,可以加快连接的速度。
  • 在经常需要根据范围进行搜索的列上创建索引,因为索引已经排序,其指定的范围是连续的。
  • 在经常需要排序的列上创建索引,因为索引已经排序,这样查询可以利用索引的排序,加快排序查询时间。
  • 在经常使用在where子句中的列上面创建索引,加快条件的判断速度。建立索引,一般按照select的where条件来建立,比如:select的条件是where f1 and f2,那么如果在字段f1或字段f2上建立索引是没有用的,只有在字段f1和f2上同时建立索引才有用。
4.4 什么样的字段不适合创建索引
  • 对于那些在查询中很少使用或者参考的列不应该创建索引。这是因为,既然这些列很少使用到,因此有索引或者无索引,并不能提高查询速度。相反,由于增加了索引,反而降低了系统的维护速度和增大了空间需求。
  • 对于那些只有很少数据值的列也不应该增加索引。这是因为,由于这些列的取值很少,例如人事表的性别,在查询的结果中,结果集的数据行占了表中数据行的很大比例,即需要在表中搜素的数据行的比例很大。增加索引,并不能明显加快检索速度。
  • 对于那些定义为text、image和bit数据数据类型的列不应该增加索引。这是因为这些列的数据量要么相当大,要么取值很少。
  • 当修改性能远远大于检索性能时,不应该创建索引。这是因为,修改性能和检索性能是互相矛盾的。当增加索引时,会提高检索性能,但是会降低修改性能。当减少索引时,会提高修改性能,降低检索性能。因此,当修改性能远远大于检索性能时,不应该创建索引。
5. MySQL中的索引种类
5.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-Tree平衡的问题;由于M/2的限制,在插入节点时,如果节点已满,需要将节点分裂为两个各占M/2的节点;删除节点时,需将两个不足M/2的兄弟节点合并。

5.2 Full-text索引

Full-text索引就是全文索引,它的存储结构也是B-Tree。主要是为了解决需要用like查询的低效问题。只能解决‘xxx%’的like查询。
如:字段数据为ABCDE,索引简历为-A、AB、ABC、ABCD、ABCDE五个。

6. MySQL中的索引管理

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

6.1 普通索引

最基本的索引,它没有任何限制,MyISAM中默认的B-Tree类型的索引,大多数情况下用到的索引。

6.1.1 创建索引
 - 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)))
6.1.2 查看索引
show index from [table_name] show keys from [table_name]  #只在MySQL中可以使用keys关键字
6.1.3 删除索引
drop index index_name on table_name
alter table table_name drop index index_name
alter table table_name drop primary key
6.2 唯一索引

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

6.2.1 创建索引
create unique index index_name on table_name(column(length))
alter table table_name add unique index_name(column(length))
create table table_name(id int not null auto_increment,title varchar(30),primary key(id),unique index_name(title(length)))
6.3 全文索引(Full Text)

MySQL从3.23版本开始支持全文索引和全文检索,Full Text索引仅可用于MyISAM表;他们可以从char、varchar或text列中作为createtable语句的一部分被创建,或是随后使用alter table或create index被添加。
对于较大的数据集,将你的资料输入一个没有Full Text索引的表中,然后创建索引,其速度比把资料输入现有Full Text索引的速度更快。不过切记对于大容量的数据表,生成全文索引是一个非常耗时间、硬盘空间的做法。

6.3.1 创建索引
create fulltext index index_name on table_name(column(length))
alter table table_name add fulltext index_name(column)
create table table_name(id int not null auto_increment,title varchar(30),primary key(id),fulltext index_name(title))
6.4 组合索引(最左前缀)

create table article(id int not null,title varchar(255),timedate);
平时用的SQL查询语句一般都有比较多的限制条件,所以为了进一步榨取MySQL的效率,就要考虑建立组合索引。例如上表中针对title和time建立一个组合索引:alter table article add index index_title_time(title(50),time(10))。建立这样的组合索引,其实是相当于分别建立了下面两组组合索引:
-title,time
-title
为什么没有time这样的组合索引呢?这是因为MySQL组合索引"最左前缀"的结果。简单的理解就是只从最左面的开始组合。并不是只要包含这两列的查询都会用到该组合索引,如下面的几个SQL所示:

  1. 使用到上面的索引
1.select * from article where title = '测试' and time = 123456789
2.select * from article where title = '测试'
  1. 不使用上面的索引
select * from article where time = 1234567890
6.4.1 创建索引
create index index_name on table_name(column_list)
7. MySQL中的索引优化

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

7.1 索引不会包含有Null值的列

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

create table table_name (c1 varchar(32) default '0')
7.2 使用短索引

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

create index index_name on table_name(column(length))
7.3 索引列排序

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

7.4 like语句操作

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

7.5 不要在列上进行运算

例如:select * from users where year(adddate) < 2007,将在每个行上进行运算,这将导致索引失效而进行全表扫描,因此可以改成:select * from users where adddate < ‘2007-01-01’

8.索引总结

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

9. MySQL中的SQL的常见优化策略
9.1 避免全表扫描

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

9.2 避免判断null值

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

select tid from t where num is null

可以在num上设置默认值0,确保表中num列没有null值,然后这样查询:

select id from t where num = 0
9.3 避免不等值判断

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

9.4 避免使用or逻辑

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

select id from t where num = 10 or num = 20

可以这样查询:

select id from t where num = 10 union all select id from t where num = 20
9.5 慎用in和not in逻辑

in和not in也要慎用,否则会导致全表扫描,如:

select id from t1 where num in (select tid from t2 where id > 10)

此时外层查询会全表扫描,不使用索引。可以修改为:

select id from t1,(select id from t1 where id > 10) t2 where t1.id = t2.id

此时索引被使用,可以明显提升查询效率。

9.6 注意模糊查询

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

select id from t where name like '%abc%'

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

select id from t where name like 'abc%'

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

9.7 避免查询条件中字段计算

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

select id from t where num / 2 = 100

应改为:

select id from t where num = 100 * 2
9.8 避免查询条件中对字段进行函数操作

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

select id from t where substring(name,1,3) = 'abc'

以abc开头的id应改为:

select id from t where name like 'abc%'
9.9 where字句"="左边注意点

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

9.10 组合索引使用

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

9.11 不要定义无意义的查询

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

select col1,col2 into #t from t where 1 = 0

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

create table #t(...)
9.12 exits

很多时候用exits代替in是一个好的选择:

select num from a where num in (select num from b)

用下面的语句替换:

select num from a where exists(select 1 from b where num = a.num)
9.13 索引也可能失效

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

9.14 表格字段类型选择

尽量使用数字型字段,若只含数值信息的字段尽量不要设计为字符型,这样降低查询和连接的性能,并会增加存储开销。这是因为引擎在处理查询和连接时会逐个比较字符串中每一个字符,而对于数字型而言只需要比较一次就够了。尽可能的使用varchar带日char,因为首先可变长度字段存储空间小,可以节省存储空间,其次对于查询来说,char在一个相对较小的字段内搜索效率显然要高些 。

9.15 查询语法中的字段

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

9.16 索引无关优化

不使用*、尽量不使用union,union all等关键字、尽量不使用or关键字、尽量使用等值判断。
表连接不建议查过5个。如果超过5个,则考虑表格的设计。(互联网应用中)
表连接方式使用外联由于内联。外连接有基础数据存在。如:A left join B,基础数据时A。A inner join B,没有基础数据的,先使用笛卡尔积完成全连接,再根据连接条件得到内连接结果集。
大数据量级的表格做分页查询时,如果页码数量过大,则使用子查询配合完成分页逻辑。

select * from table limit 1000000,10
select * from table where id in(select pk from table limit 1000000,10)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值