`

Mysql语句优化经验

 
阅读更多

Sql语句优化和索引

 

注:要善用explain去查看sql执行顺序

EXPLAIN select * from es_order o where EXISTS (select * from es_member m where o.member_id = m.member_id );

由上可知:子查询取决于外层查询集合所得到的rows=2226,对于外层每条记录都会与子查询组成新的查询语句。
所以查询时间约为0.8s。

用内连查询EXPLAIN select * from es_order o left JOIN es_member m ON  m.member_id=o.member_id ;

都是普通查询,所以查询时间约为0.004s。

   可参考:http://lopez.iteye.com/admin/blogs/2292546

可参考:http://lopez.iteye.com/admin/blogs/2292546

 

1.Innerjoin和左连接,右连接,子查询

 

A.     inner join内连接也叫等值连接是,left/rightjoin是外连接。

 

SELECT A.id,A.name,B.id,B.name FROM A LEFT JOIN B ON A.id =B.id;

 

SELECT A.id,A.name,B.id,B.name FROM A RIGHT JOIN ON B A.id= B.id;

 

SELECT A.id,A.name,B.id,B.name FROM A INNER JOIN ON A.id =B.id;

 

经过来之多方面的证实inner join性能比较快,因为inner join是等值连接,或许返回的行数比较少。但是我们要记得有些语句隐形的用到了等值连接,如:

 

SELECT A.id,A.name,B.id,B.name FROM A,B WHERE A.id = B.id;

 

推荐:能用inner join连接尽量使用inner join连接

 

B.子查询的性能又比外连接性能慢,尽量用外连接来替换子查询。

 

  Select* from A where exists (select * from B where id>=3000 and A.uuid=B.uuid);

 

A表的数据为十万级表,B表为百万级表,在本机执行差不多用2秒左右,我们可以通过explain可以查看到子查询是一个相关子查询(DEPENDENCE SUBQUERY);MySQL是先对外表A执行全表查询,然后根据uuid逐次执行子查询,如果外层表是一个很大的表,我们可以想象查询性能会表现比这个更加糟糕。

 

  一种简单的优化就是用innerjoin的方法来代替子查询,查询语句改为:

 

   Select* from A inner join B using(uuid) where b.uuid>=3000;

 

  这个语句执行测试不到一秒;

 

C.在使用ON 和 WHERE 的时候,记得它们的顺序,如:

 

SELECT A.id,A.name,B.id,B.name FROM A LEFT JOIN B ON A.id =B.id WHERE B.NAME=’XXX’

 

执行过程会先执行ON 后面先过滤掉B表的一些行数。然而WHERE是后再过滤他们两个连接产生的记录。

 

不过在这里提醒一下大家:ON后面的条件只能过滤出B表的条数,但是连接返回的记录的行数还是A表的行数是一样。如:

 

SELECT A.id,A.name,B.id,B.name FROM A LEFT JOIN B ON A.id =B.id;

 

返回的记录数是A表的条数,ON后面的条件只起到过滤B表的记录数,而

 

SELECT A.id,A.name,B.id,B.name FROM A ,B WHERE A.id = B.id

 

返回的条数,是笛卡尔积后,符合A.id = B.id这个条件的记录

 

D.使用JOIN时候,应该用小的结果驱动打的结果(left join 左边表结果尽量小,如果有条件应该放到左边先处理,right join同理反向),同时尽量把牵涉到多表联合的查询拆分多个query(多个表查询效率低,容易锁表和阻塞)。如:

 

Select * from A left join B ona.id=B.ref_id where B.ref_id>10;

 

可以优化为:select * from (select * from A wehre id >10) T1 left join B onT1.id=B.ref_id;

 

2.建立索引,加快查询性能.

 

A.在建立复合索引的时候,在where条件中用到的字段在复合索引中,则最好把这个字段放在复合索引的最左端,这样才能使用索引,才能提高查询。

 

B.保证连接的索引是相同的类型,意思就是A表和B表相关联的字段,必须是同类型的。这些类型都建立了索引,这样才能两个表都能使用索引,如果类型不一样,至少有一个表使用不了索引。

 

C.索引,不仅仅是主键和唯一键,也可以是其他的任何列。在使用like其中一个有索引的字段列的时候。

 

如: select *from A name like ‘xxx%’;

 

这个sql会使用name的索引(前提name建立了索引);而下面的语句就使用不了索引

 

Select * from A name like ‘%xxx’;

 

因为‘%’代表任何字符,%xxx不知道怎么去索引的,所以使用不了索引。

 

D.复合索引

 

比如有一条语句这样的:select* from users where area =’beijing’ and age=22;

 

如果我们是在area和age上分别创建索引的话,由于mysql查询每次只能使用一个索引,所以虽然这样已经相对不做索引时全表扫描提高了很多效 率,但是如果area,age两列上创建复合索引的话将带来更高的效率。如果我们创建了(area,age,salary)的复合索引,那么其实相当于创 建了(area,age,salary),(area,age),(area)三个索引,这样称为最佳左前缀特性。因此我们在创建复合索引的应该将最常用 作限制条件的列放在最左边,依次递减。

 

E.索引不会包含有NULL值的列

 

只要列中包含有NULL值都将不会被包含在索引中(除非是唯一值的域,可以存在一个NULL),复合索引中只要有一列含有NULL值,那么这一列对于此复合索引是无效的。所以我们在数据库设计时不要让字段的默认值为NULL.

 

F.使用短索引

 

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

 

G.排序的索引问题

 

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

 

3.limit千万级分页的时候优化。

 

A.在我们平时用limit,如:

 

Select * from A order by id limit 1,10;

 

这样在表数据很少的时候,看不出什么性能问题,倘若到达千万级,如:

 

Select * from A order by id limit10000000,10;

 

虽然都是只查询10记录,但是这个就性能就让人受不了了。所以为什么当表数据很大的时候,我们还继续用持久层框架如hibernate,ibatis就会有一些性能问题,除非持久层框架对这些大数据表做过优化。

 

B.在遇见上面的情况,我们可以用另外一种语句优化,如:

 

Select * from A where id>=(Select idfrom a limit 10000000,1) limit 10;

 

确实这样快了很多,不过前提是,id字段建立了索引。也许这个还不是最优的,其实还可以这样写:

 

Select * from A where id between 10000000and 10000010;

 

这样的效率更加高。

 

5.limit的优化:
定时器的sql示例如下:
select * from table where status=0 limit 29800,200;
select * from table where status=0 limit 30000,200;
select * from table where status=0 limit 30200,200;
limit分页到这个程度,就非常慢了。
调优办法:
select * from table where status=0 and id>0 limit 0,200;
select * from table where status=0 and id>200 limit 0,200;
select * from table where status=0 and id>400 limit 0,200;
调优后效果非常显著,sql执行起来几乎无延迟。

 

 

4.尽量避免Select * 命令

 

A.从表中读取越多的数据,查询会变得更慢。它会增加磁盘的操作时间,还是在数据库服务器与web服务器是独立分开的情况下,你将会经历非常漫长的网络延迟。仅仅是因为数据不必要的在服务器之间传输。

主要是考虑节省应用程序服务器的内存。

 

5.尽量不要使用BY RAND()命令

 

 A.如果您真需要随机显示你的结果,有很多更好的途径实现。而这个函数可能会为表中每一个独立的行执行BY RAND()命令—这个会消耗处理器的处理能力,然后给你仅仅返回一行。

 

 

 

6.利用limit 1取得唯一行

 

 A.有时要查询一张表时,你要知道需要看一行,你可能去查询一条独特的记录。你可以使用limit 1.来终止数据库引擎继续扫描整个表或者索引,如:

 

Select * from A  where name like ‘%xxx’ limit 1;

 

这样只要查询符合like ‘%xxx’的记录,那么引擎就不会继续扫描表或者索引了。

 

 

 

7.尽量少排序

 

A.排序操作会消耗较多的CPU资源,所以减少排序可以在缓存命中率高等

 

 

 

8.尽量少OR

 

 A.当where子句中存在多个条件以“或”并存的时候,Mysql的优化器并没有很好的解决其执行计划优化 问题,再加上mysql特有的sql与Storage分层架构方式,造成了其性能比较地下,很多时候使用union all或者union(必要的时候)的方式代替“or”会得到更好的效果。

 

 

 

9.尽量用union all 代替union

 

 A.union和union all的差异主要是前者需要将两个(或者多个)结果集合并后再进行唯一性过滤操作,这就会涉及到排序,增加大量的cpu运算,加大资源消耗及延迟。所以当 我们可以确认不可能出现重复结果集或者不在乎重复结果集的时候,尽量使用union all而不是union.

 

10.避免类型转换

 

A.这里所说的“类型转换”是指where子句中出现column字段的类型和传入的参数类型不一致的时候发生的类型转换。人为的上通过转换函数进行转换,直接导致mysql无法使用索引。如果非要转型,应该在传入参数上进行转换。

 

 

 

11.不要在列上进行运算

 

A. 如下面:select * fromusers where YEAR(adddate)<2007;将在每个行进行运算,这些导致索引失效进行全表扫描,因此我们可以改成:

 

Select * from users where adddate<’2007-01-01’;

 

 

 

12.尽量不要使用NOT IN和<>操作

 

A. NOT IN和<>操作都不会使用索引,而是将会进行全表扫描。NOT IN可以NOT EXISTS代替,id<>3则可以使用id>3 or id <3;如果NOT EXISTS是子查询,还可以尽量转化为外连接或者等值连接,要看具体sql的业务逻辑。

 

B.把NOT IN转化为LEFT JOIN如:

 

SELECT * FROM customerinfo WHERE CustomerIDNOT in (SELECT CustomerID FROM salesinfo );

 

优化:

 

SELECT * FROM customerinfo LEFT JOINsalesinfoON customerinfo.CustomerID=salesinfo. CustomerID WHEREsalesinfo.CustomerID IS NULL;

 

不使用exists:
select * from es_order o,es_member m  where  o.member_id = m.member_id ;
 


使用exists
select * from es_order o where EXISTS (select * from es_member m where o.member_id = m.member_id );

 

 

 

13.使用批量插入节省交互(最好是使用存储过程)

 

A. 尽量使用insert intousers(username,password) values(‘test1’,’pass1’), (‘test2’,’pass2’), (‘test3’,’pass3’);

 

 

14.对多表关联的查询,建立视图

A.对多表的关联可能会有性能上的问题,我们可以对多表建立视图,这样操作简单话,增加数据安全性,通过视图,用户只能查询和修改指定的数据。且提高表的逻辑独立性,视图可以屏蔽原有表结构变化带来的影响。

demo:

 

Create view V_term
as
select MOBILE,CERTID,GROUPID,'0' as TERMTYPE from carterm
union all select MOBILE,USERNAME,GROUPID,'1' as TERMTYPE from mobileterm 
union all select MOBILE,USERNAME,GROUPID,'2' as TERMTYPE from handsetterm 
GO
 
--调用
select * from v_term

 

15、此外,有一些优化建议

下面列举了几个常见有助于提升MySQL效率的Schema设计规范及SQL使用建议:

1、所有的InnoDB表都设计一个无业务用途的自增列做主键,对于绝大多数场景都是如此,真正纯只读用InnoDB表的并不多,真如此的话还不如用TokuDB来得划算;

2、字段长度满足需求前提下,尽可能选择长度小的。此外,字段属性尽量都加上NOT NULL约束,可一定程度提高性能;

3、尽可能不使用TEXT/BLOB类型,确实需要的话,建议拆分到子表中,不要和主表放在一起,避免SELECT * 的时候读性能太差。

4、读取数据时,只选取所需要的列,不要每次都SELECT *,避免产生严重的随机读问题,尤其是读到一些TEXT/BLOB列;

6、通常情况下,子查询的性能比较差,建议改造成JOIN写法;

7、多表联接查询时,关联字段类型尽量一致,并且都要有索引;

8、多表连接查询时,把结果集小的表(注意,这里是指过滤后的结果集,不一定是全表数据量小的)作为驱动表;

9、多表联接并且有排序时,排序字段必须是驱动表里的,否则排序列无法用到索引;

10、多用复合索引,少用多个独立索引,尤其是一些基数(Cardinality)太小(比如说,该列的唯一值总数少于255)的列就不要创建独立索引了;

11、类似分页功能的SQL,建议先用主键关联,然后返回结果集,效率会高很多;

 

分享到:
评论

相关推荐

    Effective MySQL之SQL语句最优化.pdf

    11. 经验与实践:在SQL语句优化过程中,积累经验非常重要。对常见问题的处理、性能调优案例、系统监控分析等都是优化过程中的实践环节。 由于无法从提供的文件中获取更具体的内容,这里只是对标题和描述中所提及的...

    【36】最新精选蚂蚁-MySQL语句性能优化视频教程下载 .txt

    根据提供的文件信息,我们可以推断出本教程主要围绕MySQL语句性能优化展开,这是一项非常重要的数据库管理技能,尤其对于那些处理大量数据的应用程序来说至关重要。下面将详细阐述与MySQL语句性能优化相关的知识点。...

    sql语句优化 mssql优化 mysql优化 oracle优化

    sql语句优化.chmmssql优化 mysql优化 oracle优化

    【No206】最新精选蚂蚁-MySQL语句性能优化视频教程下载

    ### MySQL语句性能优化知识点详解 #### 一、MySQL简介及优化的重要性 MySQL是一种广泛使用的开源关系型数据库管理系统(RDBMS),因其高效性、稳定性和可扩展性而在各种应用场景中备受青睐。随着数据量的增长和...

    mysql优化sql语句的优化(索引,常用小技巧.)

    综上所述,MySQL数据库的优化涉及到多个方面,包括数据库设计、SQL语句优化、数据配置以及硬件与操作系统配置等。通过综合运用这些优化方法,可以有效提升数据库系统的性能和稳定性,为用户提供更好的服务体验。

    MySQL数据库优化SQL篇PPT课件.pptx

    二、SELECT语句优化 SELECT语句是MySQL数据库中最常用的语句之一。SELECT语句的优化是非常重要的。通过优化SELECT语句,可以提高数据库的性能和效率。 三、IN和EXIST语句 IN和EXIST语句是MySQL数据库中常用的语句...

    千金良方:MySQL性能优化金字塔法则.docx

    MySQL性能优化金字塔法则是由一位知名MySQL专家提出的,该法则基于他多年的实践经验和理论研究。金字塔法则认为,MySQL性能优化的关键在于建立一个多层次的优化体系,从硬件层、操作系统层、数据库层、应用程序层到...

    百度mysql性能优化ppt

    【标题】:“百度mysql性能优化ppt”所涉及的知识点涵盖了MySQL数据库在性能调优方面的多个重要环节。在MySQL性能优化中,我们关注的核心是提升数据处理速度,减少资源消耗,从而提高系统的整体效率。 【描述】:...

    mysql语句转postgres的工具

    在这个过程中,`MysqlToPostgresUtil`工具扮演着重要的角色,它能帮助我们将MySQL的DDL(Data Definition Language)语句转换为PostgreSQL兼容的格式,从而简化迁移过程。 MySQL和PostgreSQL虽然都是关系型数据库...

    提升MYSQL查询效率的10个SQL语句优化技巧.doc

    以下是十个 SQL 语句优化技巧来提升 MYSQL 查询效率: 1. 优化 MySQL 查询缓存 MySQL 查询缓存可以启用高速查询缓存,让数据库引擎在后台悄悄的处理是提高性能的最有效方法之一。当同一个查询被执行多次时,如果...

    Effective MySQL之SQL语句最优化(高清)

    《Effective MySQL之SQL语句最优化》提供了很多可以用于... ●用SQL语句优化的生命周期来识别、确认、分析然后优化SQL语句,并检查优化的结果;  ●学习使用不为常人所知的一些性能技巧来改进索引效率并简化SQL语句。

    Effective MySQL之SQL语句最优化

    3. **查询语句优化**:理解SQL执行计划至关重要,书中可能会教你如何使用EXPLAIN分析查询执行过程。此外,避免在WHERE子句中使用函数,以及合理处理NULL值,也是优化查询的重要技巧。 4. **存储引擎的选择**:MySQL...

    《Effective MySQL之SQL语句最优化》手册

    《Effective MySQL之SQL语句最优化》是一本深入探讨如何提升数据库性能的专业手册,它针对SQL语句的优化提供了一系列实用且高效的策略。在数据库管理领域,SQL优化是提升系统性能的关键环节,尤其是在处理大数据量时...

    mysql语句跟踪.txt

    通过分析慢查询日志,可以找出数据库性能瓶颈,优化SQL语句或数据库结构,提升系统性能。 #### 配置方法 慢查询日志的开启方式与General Log和Binary Log类似,可以通过以下命令或配置文件进行设置: ```sql ...

    32丨MySQL调优之SQL语句:如何写出高性能SQL语句?.html

    32丨MySQL调优之SQL语句:如何写出高性能SQL语句?.html

    《Effective MySQL之SQL语句最优化》数据库SQL

    本篇文章将依据书中的核心概念,结合实际应用,详细介绍SQL语句优化的关键知识点。 首先,理解索引及其作用是SQL优化的基础。索引是数据库管理系统用来加速数据检索的数据结构。合理创建和使用索引可以显著提高查询...

    mysql优化笔记+资料

    二、SQL语句优化 1. 使用JOIN操作时,确保ON条件是被索引的列,并且在可能的情况下,将JOIN顺序调整为小表先于大表。 2. 减少子查询,尽可能用JOIN替换,因为子查询通常效率较低。 3. 避免在SELECT语句中使用*,明确...

    java实体转mysql建表语句

    在Java开发中,将Java实体类转换为MySQL数据库的建表语句是一项常见的任务,它有助于快速构建数据库模型,尤其在使用ORM(对象关系映射)框架如Hibernate、MyBatis时更为便捷。本篇文章将深入探讨这个过程,并提供...

Global site tag (gtag.js) - Google Analytics