MySql优化策略
MySql优化主要分为以下四大方面:
设计:存储引擎,字段类型,范式与逆范式;
功能:索引,缓存,分区分表;
架构:主从复制,读写分离,负载均衡;
合理SQL:测试,经验。
1、存储引擎
在创建表的时候使用sql语句,Create table tableName () engine=myisam|innodb;指明存储引擎是myisam还是innodb。存储引擎是一种用来存储MySQL中对象(记录和索引)的一种特定的结构(文件结构),处于MySQL服务器的最底层,直接存储数据。导致上层的操作,依赖于存储引擎的选择。
网络接口层:与客户端通信,比如传输数据等等。存储引擎层:存储数据的规则、方式。
本质:存储引擎就是特定的数据存储格式(方案)。
可以使用show engines命令来查看当前MySQL支持的存储引擎列表。
(1)、Innodb
InnoDB是一个健壮的事务型存储引擎,InnoDB还引入了行级锁定和外键约束。
Mysql版本>=5.5 默认的存储引擎,MySQL推荐使用的存储引擎。支持事务,行级锁定,外键约束。事务安全型存储引擎。更加注重数据的完整性和安全性。
①、存储格式
数据,索引集中存储,存储于同一个表空间文件中。
数据:记录行。
索引:一种检索机制,也需要一定的空间,就相当于一本字典的目录。
使用innodb引擎时,需要理解独立表空间、共享表空间。
共享表空间以及独占表空间都是针对数据的存储方式而言的。
共享表空间: 某一个数据库的所有的表数据,索引文件全部放在一个文件中,默认这个共享表空间的文件路径在data目录下。 默认的文件名为:ibdata1 初始化为10M。
独占表空间: 每一个表都将会生成以独立的文件方式来进行存储,每一个表都有一个.frm表描述文件,还有一个.ibd文件。 其中这个文件包括了单独一个表的数据内容以及索引内容。
两者之间的优缺点:
共享表空间:
优点:
可以将表空间分成多个文件存放到各个磁盘上(表空间文件大小不受表大小的限制,如一个表可以分布在不同的文件上)。数据和文件放在一起方便管理。
缺点:
所有的数据和索引存放到一个文件中意味着将有一个很大的文件,虽然可以把一个大文件分成多个小文件,但是多个表及索引在表空间中混合存储,这样对于一个表做大量删除操作后表空间中将会有大量的空隙,特别是对于统计分析,日志系统这类应用最不适合用共享表空间。
独立表空间:
优点:
a. 每个表都有自已独立的表空间。
b. 每个表的数据和索引都会存在自已的表空间中。
c. 可以实现单表在不同的数据库中移动。
d. 空间可以回收(除drop table操作处,表空间不能自已回收),对于使用独立表空间的表,不管怎么删除,表空间的碎片不会太严重的影响性能,而且还有机会处理。
缺点:
单表增加过大,如超过100个G。
相比较之下,使用独占表空间的效率以及性能会更高一点。
②、数据按照主键顺序存储:插入时做排序工作,效率低。
③、特定功能:事务、外键约束,都是为了维护数据的完整性。
并发性处理:
innodb擅长处理并发的。因为它使用了行级锁定,只该行锁了,其它行没有锁。
行级锁定:在一定情况下,可以选择行级锁来提升并发性。也支持表级锁定,Innodb会自带锁,不需要自己设置。
多版本并发控制MVCC,效果达到无阻塞读操作。
④、总结:innodb擅长事务、数据的完整性及高并发处理,不擅长快速插入(插入前要排序,消耗时间)和检索。
(2)、MyISAM存储引擎
MySQL<= 5.5 MySQL默认的存储引擎。
ISAM:Indexed Sequential Access Method(索引顺序存取方法)的缩写,是一种文件系统。
①、存储方式
数据和索引分别存储于不同的文件中。每当建立一个MyISAM引擎的表时,就会在本地磁盘上建立三个文件,文件名就是表名。
三个文件:*.frm,存储表定义;*.MYD,存储数据;*.MYI,存储索引。
MyISAM表是独立于操作系统的,可以轻松地将其从Windows服务器移植到Linux服务器;
②、数据的存储顺序为插入顺序(没有经过排序)
插入速度快,空间占用量小。
③、功能
a.全文索引支持。(mysql>=5.6时innodb 也支持)
b.数据的压缩存储。.MYD文件的压缩存储。压缩优势:节省磁盘空间,减少磁盘IO开销。特点:压缩后的表变成了只读表,不可写。如果需要更新数据,则需要先解压后更新。
c.并发性:仅仅支持表级锁定,不支持高并发。支持并发插入。写操作中的插入操作,不会阻塞读操作(其他操作)
MyISAM存储引擎特别适合在以下几种情况下使用:
①.选择密集型的表。MyISAM存储引擎在筛选大量数据时非常迅速,这是它最突出的优点。
②.插入密集型的表。MyISAM的并发插入特性允许同时选择和插入数据。
如何选择存储引擎:
Innodb :数据完整性,并发性处理,擅长更新,删除。
myisam:高速查询及插入。擅长插入和查询。
(3)、其他存储引擎
①、MEMORY存储引擎的出发点是速度。为得到最快的响应时间,采用的逻辑存储介质是系统内存。虽然在内存中存储表数据确实会提供很高的性能,但当mysqld守护进程崩溃时,所有的Memory数据都会丢失。获得速度的同时也带来了一些缺陷。它要求存储在Memory数据表里的数据使用的是长度不变的格式,这意味着不能使用BLOB和TEXT这样的长度可变的数据类型,VARCHAR是一种长度可变的类型,但因为它在MySQL内部当做长度固定不变的CHAR类型,所以可以使用。
一般在以下几种情况下使用Memory存储引擎:a、目标数据较小,而且被非常频繁地访问;b、如果数据是临时的,而且要求必须立即可用,那么就可以存放在内存表中;c、存储在Memory表中的数据如果突然丢失,不会对应用服务产生实质的负面影响。
Memory同时支持散列索引和B树索引。B树索引的优于散列索引的是可以使用部分查询和通配查询,也可以使用<、>和>=等操作符方便数据挖掘。散列索引进行“相等比较”非常快,但是对“范围比较”的速度就慢多了,因此散列索引值适合使用在=和<>的操作符中,不适合在<或>操作符中,也同样不适合用在order by子句中。
②、MERGE存储引擎是一组MyISAM表的组合,这些MyISAM表结构必须完全相同,尽管其使用不如其它引擎突出,但是在某些情况下非常有用。Merge表就是几个相同MyISAM表的聚合器;Merge表中并没有数据,对Merge类型的表可以进行查询、更新、删除操作,这些操作实际上是对内部的MyISAM表进行操作。
Merge存储引擎的使用场景:对于服务器日志这种信息,一般常用的存储策略是将数据分成很多表,每个名称与特定的时间段相关。例如:可以用12个相同的表来存储服务器日志数据,每个表用对应各个月份的名字来命名。当有必要基于所有12个日志表的数据来生成报表,这意味着需要编写并更新多表查询,以反映这些表中的信息。与其编写这些可能出现错误的查询,不如将这些表合并起来使用一条查询,之后再删除Merge表,而不影响原来的数据,删除Merge表只是删除Merge表的定义,对内部的表没有任何影响。
③、Archive:存档型,仅提供插入和查询操作。非常高效阻塞的插入和查询。
锁的概念:当客户端操作表时,为了保证操作的隔离性,通过加锁来处理。
读锁:读操作时增加的锁,也叫共享锁。特征是阻塞其他客户端的写操作,不阻塞读操作(并发读)。
写锁:写操作时增加的锁,也叫独占锁或排他锁。特征是阻塞其他客户端的读,写操作。
行级锁:提升并发性,锁本身开销大。
表级锁:不利于并发性,锁本身开销小。
2、字段类型选择
字段类型应尽量满足以下需求:
尽可能小(占用存储空间少)、尽可能定长(占用存储空间固定)、尽可能使用整数。
(1)、字段类型介绍
①、数组类型
a、整型
MySQL数据库支持五种整型类型,包括:TINYINT、SMALLINT、MEDIUMINT、INT和BIGINT五种。
五种整型的适用场景:
TINYINT,年龄,包含在0~255之间;
SMALLINT,端口号,包含在0~65535之间;
MEDIUMINT,中小型网站注册会员,1600万够用;
INT,身份证编号,42亿可以用很久;
BIGINT,Twitter微博量,几百亿
b、浮点型(非精确)
MySQL数据库支持两种浮点类型:FLOAT(单精度)和DOUBLE(双精度)两种
c、定点型(精确)
浮点型由于内部的存储方式是数值,导致它在一定程度上取得的是近似值而非精确值。如果使用定点型,那么就可以精确取得小数部分,因为它内部存储方式是字符串形式。
创建一个定点型格式:DECIMAL(M,D),表示小数点D位,整数部分M位及M位内。
②、日期类型
MySQL数据库中有五个可用的日期时间数据类型,分别为:DATE、DATETIME、TIME、YEAR、TIMESTAMP。
③、字符类型
a、CHAR
保存定长字符串,CHAR(5)表示必须保存5个字符。由于CHAR类型是定长,MySQL会根据定义的长度进行分配空间,在处理速度上比VARCHAR快的多,所以适合存储例如手机、身份证这种定长的字符,否则就会造成浪费。
b、VARCHAR
保存变长字符串,VARCHAR(5)则表示最大保存字符为5。
c、BINARY和VARBINARY
采用二进制存储的,没有字符集概念,意义在于防止字符集的问题导致数据丢失,存储中文会占用两个字符,会乱码,半截会问号。因为是采用二进制存储,在比较字符和排序的时候,都是二进制进行的,所以只有需要操作二进制时才需要使用。
④、八种适合文本内容的大数据类型:TINYTEXT、TEXT、MEDIUMTEXT、LONGTEXT、TINYBLOG、BLOB、MEDIUMTEXT、LONGTEXT。
综上:短文本定长用char,变长用varchar,长文本用text
⑤、类型属性
无符号(UNSIGNED)和填充零(ZEROFILL),是否为空、默认值、主键、自动编号。
(2)、字段类型选择
越小的列会越快:对于大多数的数据库引擎来说,硬盘操作可能是最重大的瓶颈。所以,把数据变得紧凑会对这种情况非常有帮助,因为这减少了对硬盘的访问。如果一个表只会有几列(比如字典表,配置表),那么,就没有必要使用INT来做主键,使用MEDIUMINT, SMALLINT 或是更小的 TINYINT 会更经济一些。如果你不需要记录时间,使用DATE要比DATETIME好得多。当然,你也需要留够足够的扩展空间。
①、永远为每张表设置一个ID
应该为数据库里的每张表都设置一个ID做为其主键,而且最好的是一个INT型的(推荐使用UNSIGNED),并设置上自动增加的 AUTO_INCREMENT标志。就算是表中有一个主键叫 “email”的字段,也别让它成为主键。使用 VARCHAR 类型来当主键会使用得性能下降。另外,在程序中,应该使用表的ID来构造你的数据结构。在MySQL数据引擎下,有一些操作(集群、分区)需要使用主键, 在这些情况下,主键的性能和设置变得非常重要。
只有一个情况是例外,即关联表的外键,也就是说,这个表的主键,通过若干个别的表的主键构成。这个情况叫做外键。比如:一个学生表有学生的ID,一个课程表有课程ID,那么,成绩表就是关联表了,其关联了学生表和课程表,在成绩表中,学生ID和课程ID叫外键,其共同组成主键。
②、使用ENUM而不是VARCHAR
ENUM类型是非常快和紧凑的。在实际上,其保存的是 TINYINT,但其外表上显示为字符串。用这个字段来做一些选项列表相当的完美。如果有一个字段,比如性别、国家、民族、状态、部门,这些字段的取值是有限且固定的,那么,应该使用 ENUM 而不是 VARCHAR。
③、尽可能的使用NOT NULL
除非有一个很特别的原因去使用NULL值,否则应该总是让你的字段保持NOT NULL。
④、把IP地址存成UNSIGNED INT
使用整形来存放IP地址,只需要4个字节,其是定长的字段,会带来查询上的优势,尤其是当需要使用这样的WHERE条件:IP between ip1 and ip2。
⑤、固定长度的表会更快
如果表中的所有字段都是“固定长度”的,整个表会被认为是static或fixed-length。 固定长度的表会提高性能,因为MySQL搜寻得会更快一些,因为这些固定的长度是很容易计算下一个数据的偏移量的,所以读取的自然也会很快。而如果字段不是定长的,那么,每一次要找下一条的话,需要程序找到主键。固定长度的表也更容易被缓存和重建。唯一的副作用是, 固定长度的字段会浪费一些空间,因为定长的字段无论用不用,都要分配那么多的空间。
⑥、垂直分割
垂直分割是一种把数据库中的表按列变成几张表的方法,这样可以降低表的复杂度和字段的数目,从而达到优化的目的。
3、范式和逆范式
①、范式
为了建立冗余较小、结构合理的数据库,设计数据库时必须遵循一定的规则。在关系型数据库中这种规则就称为范式。范式是符合某一种设计要求的总结。要想设计一个结构合理的关系型数据库,必须满足一定的范式。
第一范式1NF,原子性:具有原子性,确保每列保持原子性。
第二范式2NF,消除部分依赖:主键列与非主键列遵循完全函数依赖关系,确保表中的每列都和主键相关。
第三范式3NF,消除传递依赖:非主键列之间没有传递函数依赖关系索引,确保每列都和主键列直接相关,而不是间接相关。
②、逆范式
逆范式是指打破范式,通过增加冗余或重复的数据来提高数据库的性能。
4、索引
利用关键字,就是记录的部分数据(某个字段,某些字段,某个字段的一部分),建立与记录位置的对应关系,就是索引。索引的关键字一定是排序的。索引本质上是表字段的有序子集,它是提高查询速度最有效的方法。一个没有建立任何索引的表,就相当于一本没有目录的书,在每次查询时就会进行全表扫描,这样会导致查询效率极低、速度也极慢。如果建立索引,那么就好比一本添加的目录,通过目录的指引,迅速翻阅到指定的章节,提升的查询性能,节约了查询资源。
(1)、索引种类:从索引的定义方式和用途来看,索引分为主键索引,唯一索引,普通索引,全文索引。
(2)、索引原则
如果索引不遵循使用原则,则可能导致索引无效。
a、列独立:如果需要某个字段上使用索引,则需要在字段参与的表达中,保证字段独立在一侧。
语句三就不是列独立,索引失效。
b、左原则
Like:匹配模式必须要左边确定不能以通配符开头。
假如业务逻辑上出现: field like ‘%keywork%’;类似查询,需要使用全文索引。
复合索引:一个索引关联多个字段,仅仅针对左边字段有效果。
示例:添加复合索引
对ename查询使用索引,对empno查询不使用索引。
(3)、OR的使用
必须要保证 OR 两端的条件都存在可以用的索引,该查询才可以使用索引。
(4)、MySQL智能选择
即使满足了上面说原则,MySQL也能弃用索引
弃用索引的主要原因:查询即使使用索引,会导致出现大量的随机IO,相对于从数据记录的第一条遍历到最后一条的顺序IO开销,还要大。
综上归纳:
a、不要过度索引。索引越多,占用空间越大,反而性能变慢;
b、在WHERE、ORDER BY、GROUP BY中频繁使用的列建立索引;
c、尽可能使用唯一索引,重复值越少,索引效果越强;
d、使用短索引,如果char(255)太大,应该给它指定一个前缀长度,大部分情况下前10位或20位值基本是唯一的,那么就不要对整个列进行索引;
e、充分利用左前缀,这是针对复合索引,因为WHERE语句如果有AND并列,只能识别一个索引(获取记录最少的那个),索引需要使用复合索引,那么应该将WHERE最频繁的放置在左边。
f、在建有索引的字段上尽量不要使用函数进行操作,否则索引失效。
g、避免在查询中让MySQL进行自动类型转换,转换过程也会使索引失效。
h、在Join表时使用相当类型的例,并将其索引
如果应用程序有很多JOIN 查询,应该确认两个表中Join的字段是被建过索引的。这样,MySQL内部会启动优化Join的SQL语句的机制。而且这些被用来Join的字段,应该是相同类型的。例如:如果你要把DECIMAL字段和一个INT字段Join在一起,MySQL就无法使用它们的索引。对于那些STRING类型,还需要有相同的字符集才行。
(5)、索引的使用场景
a、索引检索:检索数据时使用索引。
b、索引排序:如果order by 排序需要的字段上存在索引,则可能使用到索引。
c、索引覆盖:索引拥有的关键字内容,覆盖了查询所需要的全部数据,此时,就不需要在数据区获取数据,仅仅在索引区即可。覆盖就是直接在索引区获取内容,而不需要在数据区获取。
例如,利用名字检索:
可以在ename字段建立索引:
分析执行:
再增加一个索引:
完成相同的查询:
查询的字段刚好是复合索引包含的字段。所以就使用了复合索引。
说明,不是非要查询用到,才可以索引覆盖,只要满足要求都可以覆盖!
建立索引索引时,不要仅仅考虑where检索,同时考虑其他的使用场景。(在所有的where字段上增加索引,就是不合理的)
(6)、前缀索引
前缀索引是建立索引关键字一种方案。通常会使用字段的整体作为索引关键字。有时,即使使用字段前部分数据,也可以去识别某些记录。就比如一个班级里,我要找王xx,假如姓王的只有1个人,那么就可以建一个前缀索引,就是王。
语法:Index `index_name` (`index_field`(N))使用index_name前N个字符建立的索引。
那么N究竟是多少?使用N长度所达到的辨识度,极限接近于使用全部长度的辨识度即可!
先计算最大的辨识度M:
公式:先计算总的记录数m,再求该字段不重复的记录数q,那么M=m/q。然后依次取得前N个字符,N逐步增加,进行对比,直到找到极限接近于M的,那么最后的N就是我们要找的N。
TIP:前缀索引不能用于索引覆盖!
(7)、全文索引
该类型的索引特殊在:关键字的创建上。是为了解决 like‘%keyword%’这类查询的匹配问题。
(8)、聚集(簇)索引和非聚集(簇)索引
(9)、EXPLAIN你的SELECT查询
使用EXPLAIN关键字可以让你知道MySQL是如何处理SQL语句的。这可以帮助分析查询语句或是表结构的性能瓶颈。EXPLAIN的查询结果还会告诉你索引主键被如何利用的,数据表是如何被搜索和排序的等等。
5、查询缓存
将select的结果,存取起来共二次使用的缓存区域:
开启缓存并设置缓存大小:
注意事项:查询缓存存在判断是严格依赖于select语句本身的:严格保证SQL一致。
如果查询时包含动态数据,则不能被缓存。
例如:
上面两条SQL语句的差别就是 CURDATE() ,MySQL的查询缓存对这个函数不起作用。所以,像 NOW() 和 RAND() 或是其它的诸如此类的SQL函数都不会开启查询缓存,因为这些函数的返回是会不定的易变的。所以,用一个变量来代替MySQL的函数,从而开启缓存。
一旦开启查询缓存,MySQL会将所有可以被缓存的select语句都缓存。如果存在不想使用缓存的SQL执行,则可以使用 SQL_NO_CACHE语法提示达到目的:
缓存仅当数据表的记录改变时,缓存才会被删除。而不是依靠过期时间的。
6、分区分表
分表和表分区的目的就是减少数据库的负担,提高数据库的效率,即提高表的增删改查效率。
(1)、分区
分区partition是将数据分段划分在多个位置存放,可以是同一块磁盘也可以在不同的机器。分区后,表面上还是一张表,但数据散列到多个位置了。应用程序读写的时候操作的还是大表名字,数据库自动去组织分区的数据。
其实每个分区,就是独立的表。都要存储该分区数据的数据,索引等信息。
创建分区:在创建表时,指定分区的选项:
Create table table_name (定义)
Partition by 分区算法 (参数) 分区选项。
采用key取余算法,根据id的值进行取余,即对5取余,然后分配到5个区里。
Tip:分区与存储引擎无关,是MySQL逻辑层完成的。
可以通过变量查看当前mysql是否支持分区:
①、分区算法
MySQL提供4种分区算法:
取余:Key,hash
条件:List,range 。
参与分区的参数字段需要为主键的一部分。
a、KEY – 取余 ,按照某个字段进行取余
分成5个区,就是对5取余。将id对5取余。
b、Hash – 取余,按照某个表达式的值进行取余
示例:学生表分区,按照生日的月份,划分到12个表中。
注意:Key,hash都是取余算法,要求分区参数(括号里的),返回的数据必须为整数。
c、List – 条件 – 列表,需要指定的每个分区数据的存储条件。
示例:按照生日中的月份,分成春夏秋冬四个分区。
List,条件依赖的数据是列表形式。
d、Range - 条件 – 范围, 条件依赖的数据是一个条件表达式。
逻辑:按照生日的年份分成不同的年龄段。
②、分区的管理与选择
a、取余:key,hash
增加分区数量: add partition partitions N
减少分区数量:coalesce partition N
采用取余算法的分区数量的修改,不会导致已有分区数据的丢失,因为会重新分配数据到新的分区。
b、条件:list,range
添加分区:
删除分区:
注意:删除条件算法的分区,会导致分区数据丢失。添加分区不会。
③、选择分区算法
平均分配:按照主键进行key(primary key)即可(非常常见)
按照某种业务逻辑分区:选择那种最容易被筛选的字段,整数型
(2)、分表
分表是将一个大表按照一定的规则分解成多张具有独立存储空间的实体表,我们可以称为子表,每个表都对应三个文件,MYD数据文件,.MYI索引文件,.frm表结构文件。这些子表可以分布在同一块磁盘上,也可以在不同的机器上。app读写的时候根据事先定义好的规则得到对应的子表名,然后去操作它。分表技术是比较麻烦的,需要手动去创建子表,服务端读写时候需要计算子表名。采用merge好一些,但也要创建子表和配置子表间的union关系。(需要手动分表)
分表是分区之前用的,MYSQL5.1后,就开始用分区代替分表了。分表很少用了。
①、水平分表:创建结构相同的N个表
②、垂直分表:
一张表中存在多个字段。这些字段可以分为常用字段和非常用字段,为了提高查表速度,可以把这两类字段分开来存储。主要目的,减少每条记录的长度。
通常按以下原则进行垂直拆分:
把不常用的字段单独放在一张表;
把text,blog等大字段拆分出来放在附表中;
经常组合查询的列放在一张表中。
7、服务器架构
(1)、主从复制:
Mysql服务器内部支持复制功能,仅仅需要通过配置完成下面的拓扑结构。一主多从典型结果:主服务器负责写数据。从服务器负责读数据。复制功能mysql自带。
(2)、读写分离、负载均衡
客户端不再操作MYSQL数据库服务器,而是去操作读写分离、负载均衡服务器。读写分离是指该服务器会判断客户端的操作是读还是写,从而选择操作mysql主服务器还是从服务器。负载均衡算法是指客户端读操作时,主服务器会根据取余算法去选择一台从服务器。
上面的架构可以提升整体服务器的效率,高性能。
同时,服务器架构需要保证,高可用(稳定),7x24不宕机。因此需要增加一些冗余服务器以便备用。时时检测正在用的服务器。
8、优化SQL
(1)、对于并发性的SQL
①、尽量少用或者不用多表操作(子查询,联合查询),而是将复杂的SQL拆分多次执行。如果查询很原子、很小,会增加查询缓存的利用率。
②、拆分大的 DELETE 或 INSERT 语句
如果需要在一个在线的网站上去执行一个大的DELETE或INSERT操作,要避免这些操作使整个网站停止响应。因为这两个操作是会锁表的,表一锁住了,别的操作都进不来了。所以,如果有一个大的处理,一定把其拆分,使用 LIMIT 条件是一个好的方法。
③、使用join连接代替子查询
使用子查询可以一次性的完成很多逻辑上需要多个步骤才能完成的SQL操作,同时也可以避免事务或者表锁死,并且写起来也很容易。但是,有些情况下,子查询可以被更有效率的JOIN连接替代。JOIN连接之所以更有效率一些,是因为MySQL不需要在内存中创建临时表。
(2)、大量数据的插入
多条 insert或者Load data into table(从文件里载入数据到表里),建议关闭约束及索引,完成数据插入,再重新生成索引及约束。
①、针对于myisam存储引擎
Alter table table_name disable keys; 禁用索引约束
大量的插入
Alter table table_name enable keys; 启用
②、针对innodb存储引擎
Drop index, drop constraint 删除索引及约束,要保留主键
Begin transaction|set autocommit=0; 开启事务,不让他自动提交
[数据本身已经按照主键值排序]
大量的插入
Commit;
Add index, add constraint
(3)、分页
①、分页假定Limit offset, size; size = 10;
Limit 的使用,会大大提升无效数据的检索,因为是先检索,检索会检索全部,再取得想要的。好的做法是使用条件等过滤方式,将检索到的数据尽可能精确定位到需要的数据上。
②、当只要一行数据时使用limit 1;
当查询表时,如果已经知道只会有一条结果,或是检查是否有返回记录数。在这种情况下,加上LIMIT 1可以增加性能。这样,MySQL数据库引擎会在找到一条数据后停止搜索,而不是继续往后查少下一条符合的记录数据。
(4)、随机选一些数据时,不要使用Order by Rand()
上面的查询,会导致每条记录都执行rand(),成本很高!
建议,通过mt_rand(),先确定的随机主键,再从数据表中获取数据。
(5)、避免 SELECT *
从数据库里读出越多的数据,那么查询就会变得越慢。并且,如果数据库服务器和WEB服务器是两台独立的服务器,还会增加网络传输的负载。所以,应该养成需要什么就取什么的好习惯。
(6)、使用联合(UNION)来代替手动创建的临时表
MySQL从4.0的版本开始支持union查询,它可以把需要使用临时表的两条或更多的select查询合并的一个查询中。在客户端的查询会话结束的时候,临时表会被自动删除,从而保证数据库整齐、高效。使用union来创建查询时,只需要用UNION作为关键字把多个select语句连接起来就可以了,要注意的是所有select语句中的字段数目要想同。
9、开启慢查询日志
定位执行较慢的查询语句方案。
slow_query_log = 0|1
long_query_time = N 超过该时间临界点,就为慢查询。
开启日志:set global slow_query_log=1; set long_query_time=0.5;