`
sqe_james
  • 浏览: 262274 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

MySQL SQL优化小结

阅读更多

优化是一个综合复杂的问题,涉及到硬软件平台。这里仅就MySQL5.0 SQL 查询语句方面作个小结。先举个例子:

现在表register(PRIMARY KEY regId),service(PRIMARY KEY servId, index serviceId )和subscribe(PRIMARY KEY subId,FOREIGN KEY regId/servId),且前两表跟后张表均为一对多关联,假设有如下表格结构:

CREATE TABLE `subscribe` (
  `subId` int(10) unsigned NOT NULL auto_increment,
  `subcribeTime` datetime NOT NULL,
  `expireTime` datetime NOT NULL,
  `cancelTime` datetime default NULL,
  `paymoney` double NOT NULL,
  `paymentTime` datetime NOT NULL,
  `payWay` tinyint(3) unsigned NOT NULL,
  `subcribeStatus` tinyint(3) unsigned NOT NULL,
  `paymentStatus` tinyint(3) unsigned NOT NULL,
  `createTime` datetime NOT NULL,
  `regId` int(10) default NULL,
  `servId` int(10) default NULL,
  PRIMARY KEY  (`subId`),
  KEY `FK_REGID` (`regId`),
  KEY `FK_SERVID` (`servId`),
  CONSTRAINT `FK_REGID` FOREIGN KEY (`regId`) REFERENCES `register` (`regId`) 
ON DELETE CASCADE,
  CONSTRAINT `FK_SERVID` FOREIGN KEY (`servId`) REFERENCES `service` (`servId`) 
ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

现在一业务根据条件subscribe.subcribeStatus=1 或 >=3 AND subscribe.expireTime <= now() 要取得subscribe.subId,register.phoneNum,service.serviceId 三个字段信息列表。测试中三表中各有三条数据具结果亦为3,初始sql 语句及执行结果如下:

这是一条最容易想到的SQL 语句,虽然优化器默认采用type 快速的indexeq_ref 类型,但suref 均为NULL 意味着将全表扫描,并 产生一个笛卡尔乘积。对于这个实例由于各表都有3行数据,即扫描3*3*1=9 行。如果表中数据是99999,那么将是99999*99999*1=? ,你可以想象它将花多长时间……,如果是关键业务这将是一场恶梦。 那有没什么办法尽最大可能地减少这个笛卡尔乘积呢?先看看优化器对上面最终执行的语句:

可以看到优化器将使用内连接来执行这个语句,这将是一个考虑的优化点,再看看这有许多WHERE 条件,这可不可以做反应优化呢?

分析一下,可以看到这些WHERE 条件中起实质限定作用的 均与subscribe 这张表有关 ,那就从这开始吧, u.subcribeStatus>=3 OR u.subcribeStatus=1 这个语句看起来有点不顺眼 (可能是因为有个OR,呵呵 ~),既然1到3中只2除外,那有没可能去掉这个OR 呢? 看一下业务需求,原来subscribeStatus 只有1至4的值,很明显这个写法不妥。 可以改为u.subcribeStatus <>2 其它条件看起来没什么问题。再来看看联接查询方面的。 既然所有限定条件都是u 表的,那么自然想到查询应该从u 表开始搜索,这可以使用左/右联接,看个人爱好。 看一下最终语句的执行结果:

可看到笛卡尔积变成了:3*1*1=3 ,相对前者多了个ref 引用,虽然已经很“完美”了,但不可避免有个表type=all 意味着将根据条件进行全表扫描。再看看优化器的执行方式:

很显然,它按我们优化方向执行,先从u 开始再联接s /r (这两次序无所谓)查询。就这个示例,我们也只能优化到这里,看看笛卡积,效果还是相当不错的,少了一个数量级的扫描。根据SHOW WARNINGS 最终SQL 为(ON 条件中也可以不用括号):

SELECT u.subId, r.phoneNum, s.serviceId FROM subscribe as u LEFT JOIN service as s
 ON (s.servId=u.servId) LEFT JOIN register as r ON (r.regId=u.regId)
 WHERE u.subcribeStatus<>=? AND u.expireTime <= now() LIMIT ?,?

 

通过上面示例,可以知道MySQL 提供的一些工具非常实用,下面介绍一下刚才用过的:

1. GRANT 语句尽量简单,以降低不必要的许可检查开销;
2. 如果问题与具体MYSQL表达式或函数有关,可使用BENCHMARK() 函数执行定时测试,语法:BENCHMARK(loop_count,expression) ;
3. EXPLAIN可作为DESCRIBE的同义词,它将解释MySQL如何处理SELECT语句,提供有关表如何联接和联接的次序信息,这对优化SQL 语句特别是级联查询时特别有用。

4. SHOW WARNINGS 可以浏览EXTENDED 产生的附加信息,输出优化器重写并优化后的SELECT语句,可能还包括优化过程的其它注解。
EXPLAIN 语法及等价SQL 语句如下:
EXPLAIN tbl_name / EXPLAIN [EXTENDED] SELECT select_options
EXPLAIN tbl_name = DESCRIBE tbl_name = SHOW COLUMNS FROM tbl_name


          何时须为表加入索引以得到更快的SELECT
         /
主要用途:
         \
          知道优化器是否以一个最佳次序联接表

 

 

WHERE子句优化

1. MySQL能更高效地在声明具有相同类型和尺寸的列上使用索引,所以在类型相同时尽量保持相同尺寸(如对于固定大小的使用char类型),如果数据经常修改的话CHAR要优于VARCHAR。因为定长的行并不会有存储残片。对于非常短的列,CHAR要比VARCHAR高效。

 

2.去除不必要的括号

e.g. ((a AND b) AND c OR (((a AND b) AND (c AND d))))
   -> (a AND b AND c) OR (a AND b AND c AND d)

 

3. 常量重叠

e.g. (a < b AND b = c) AND a = 5
   -> b > 5 AND b = c AND a = 5

 

4. 去除常量条件(由于常量重叠需要):

 e.g. (B>=5 AND B=5) OR (B=6 AND 5=5) OR (B=7 AND 5=6)
   -> B=5 OR B=6

 

5. 如果不使用GROUP BY或分组函数(COUNT()、MIN()……),HAVING与WHERE合并。

 

6. 对于联接内的每个表,构造一个更简单的WHERE以便更快地对表进行WHERE计算并且也尽快跳过记录。

 

7. 所有常数的表在查询中比其它表先读出。常数表为:
   空表或只有1行的表。
   与在一个PRIMARY KEY或UNIQUE索引的WHERE子句一起使用的表,这里所有的索引部分使用常数表达式并且索引部分被定义为NOT NULL。


e.g.下列的所有表用作常数表:
mysql> SELECT * FROM t WHERE primary_key=1;
mysql> SELECT * FROM t1,t2 WHERE t1.primary_key=1 AND t2.primary_key=t1.id

 

 

待续。。。。

 

分享到:
评论

相关推荐

    2021年MySQL高级教程视频.rar

    16.MySQL高级锁MyISAM表锁小结.avi 17.MySQL高级锁MyISAM表锁查看锁争用情况.avi 18.MySQL高级锁InnoDB行锁介绍及背景知识.avi 18.MySQL高级锁InnoDB行锁类型.avi 19.MySQL高级锁InnoDB行锁基本演示.avi 20.MySQL...

    MySQL常见面试题(小结).pdf

    《MySQL常见面试题(小结).pdf》是一份针对MySQL面试常见问题的小结资料,内容涵盖了MySQL基础知识、SQL语句、索引优化、备份与恢复等方面的面试题目。适用于准备MySQL相关岗位面试的求职者、MySQL初学者以及想要巩固...

    SQL SERVER 的SQL语句优化方式小结

    1、SQL SERVER 2005的性能工具中有SQL Server Profiler和数据库引擎优化顾问,极好的东东,必须熟练使用。 2、查询SQL语句时打开“显示估计的执行计划”,分析每个步骤的情况 3、初级做法,在CPU占用率高的时候,...

    2017最新老男孩MySQL高级专业DBA实战课程全套【清晰不加密】,看完教程月入40万没毛病

    8-MySQL数据库SQL优化生产方案及细节精讲04.avi 9-MySQL数据库架构优化生产方案及细节精讲05.avi 第十六部 MySQL业务变更流程与安全管理思想(7节) 01-安全优化-项目开发流程及数据库更新流程.avi 02-DBA参与项目...

    Mysql数据库之sql基本语句小结

    本文实例讲述了Mysql数据库之sql基本语句。分享给大家供大家参考,具体如下: SQL基本语句 1.登录退出及快捷键: (1)快捷键: ————快速回到行首 ctrl + a ————回到行末 ctrl + e ————清屏 ctrl + l ...

    mysql和oracle的区别小结(功能性能、选择、使用它们时的sql等对比)

    一、并发性 ...oracle使用行级锁,对资源锁定的粒度要小很多,只是锁定sql需要的资源,并且加锁是在数据库中的数据行上,不依赖与索引。所以oracle对并发性的支持要好很多。 二、一致性 oracle: oracle支持s

    MySQL5.1性能调优与架构设计.mobi

    如MySQL Schema设计的技巧,Query语句的性能优化方式方法及MySQL Server中SQL层和存储引擎层的优化思路。同时还分析了MySQL数据库中主要存储引擎的锁定机制 ●架构设计篇则主要以设计一个高可用可扩展的分布式企业级...

    六条比较有用的MySQL数据库操作的SQL语句小结

    在MySQL数据库操作中,我们常常编写一些SQL语句来实现自己想要的功能。但是对于初学MySQL数据库的人来说这似乎又有一定的难度。本文我们总结了六条比较有用的SQL语句,初学者可以套用下面的格式,接下来就让我们一...

    MySQL定期分析检查与优化表的方法小结

    MySQL使用已存储的关键字分布来决定,当您对除常数以外的对象执行联合时,表按什么顺序进行联合。 mysql&gt; analyze table a; +——–+———+———-+—————————–+ | Table | Op | Msg_type | M

    MYSQL表优化方法小结 讲的挺全面

    同时在线访问量继续增大 对于1G内存的服务器明显感觉到吃力严重时甚至每天都会死机 或者时不时的服务器卡一下 这个问题曾经困扰了我半个多月MySQL使用是很具伸缩性的算法,因此你通常能用很少的内存运行或给MySQL更...

    MySQL 建表的优化策略 小结

    目录 1. 字符集的选择 1 2. 主键 1 3. 外键 2 4. 索引 2 4.1. 以下情况适合于创建索引 2 4.2. 以下的情况下不适合创建索引 3 4.3. 联合索引 3 4.4. 索引长度 4 5. 特殊字段 4 5.1.... 采用UTF-8编码会占用3个字节,而...

    Mysql中基本语句优化的十个原则小结

    主要给大家总结介绍了Mysql中基本语句优化的十个原则,通过学习与记住它们,在构造sql时可以养成良好的习惯,文中介绍的相对比较详细与简单明了,需要的朋友们可以参考借鉴,下面来一起看看吧。

    MySQL DBA 常用手册小结

    1.mysql的远程连接命令可以远程导入导出数据 mysqldump –default-character-set=gb2312 -h255.255.000.00 -uroot -pxxxxxx mydatabase&gt;d:\data.sql 将指定的数据库导出到一个外部SQL文件中去! 还原命令: mysql –...

    MySQL数据库优化推荐的编译安装参数小结

    MySQL编译参数多而复杂,让新手感到很头大,如果是正式生成环境安装MySQL,没有充足的时间去研究每一个参数代表的意义,个人建议使用余洪春前辈整理的编译参数,便捷高效! MySQL的线上安装建议采取编译安装的方法,...

    MySQL 5权威指南(第3版) 中文版 下载地址

     1.7 小结  第2章 测试环境  2.1 是Windows还是UNIX/Linux  2.2 在Windows系统上安装MySQL和相关软件  2.3 在SUSE Linux 9.3系统上安装MySQL和相关软件  2.4 在Red Hat Enterprise Linux 4系统上安装...

    MySQL慢日志实践小结

    慢查询主要是为了我们做sql语句的优化功能. 慢查询配置项说明 登录mysql服务,使用如下命令 mysql&gt; show variables like '%query%'; +------------------------------+-----------------------------------------+...

    sqlserver分页查询处理方法小结

    sqlserver2008不支持关键字limit ,所以它的分页sql查询语句将不能用MySQL的方式进行,幸好sqlserver2008提供了top,rownumber等关键字,这样就能通过这几个关键字实现分页。 下面是本人在网上查阅到的几种查询脚本...

    MySQL无法启动几种常见问题小结

    错误信息例如: 代码如下:[code] mysqld_safe Starting mysqld daemon with databases from /usr/local/mysql/data /usr/local/mysql/bin/mysqld_safe: line 107: /usr/local/mysql/data/imysql.

Global site tag (gtag.js) - Google Analytics