MySQL数据库查询优化技巧

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

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

select id from t where num is null

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

select id from t where num=0

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

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

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

可以这样查询:

select id from t where num=10union allselect id from t where num=20

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

select id from t where num in(1,2,3)

对于连续的数值,能用 between 就不要用 in 了:

select id from t where num between 1 and 3

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

select id from t where name like ‘%abc%

若要提高效率,可以考虑全文检索。

7.如果在 where 子句中使用参数,也会导致全表扫描。因为SQL只有在运行时才会解析局部变量,但优化程序不能将访问计划的选择推迟到运行时;它必须在编译时进行选择。然 而,如果在编译时建立访问计划,变量的值还是未知的,因而无法作为索引选择的输入项。如下面语句将进行全表扫描:

select id from t where num=@num <mailto:num=@num>

可以改为强制查询使用索引:

select id from t with(index(索引名)) where num=@num <mailto:num=@num>

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

select id from t where num/2=100

应改为:

select id from t where num=100*2

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

select id from t where substring(name,1,3)=’abc’–name以abc开头的idselect id from t where datediff(day,createdate,2005-11-30)=0–‘2005-11-30’生成的id

应改为:

select id from t where name like ‘abc%’select id from t where createdate>=2005-11-30′ and createdate<2005-12-1

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

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

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

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

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

create table #t()

13.很多时候用 exists 代替 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)

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

率起不了作用。

15.索引并不是越多越好,索引固然可以提高相应的 select 的效率,但同时也降低了 insert 及 update 的效率,因为 insert 或 update 时有可能会重建索引,所以怎样建索引需要慎重考虑,视具体情况而定。一个表的索引数最好不要超过6个,若太多则应考虑一些不常使用到的列上建的索引是否有 必要。

16.应尽可能的避免更新 clustered 索引数据列,因为 clustered 索引数据列的顺序就是表记录的物理存储顺序,一旦该列值改变将导致整个表记录的顺序的调整,会耗费相当大的资源。若应用系统需要频繁更新 clustered 索引数据列,那么需要考虑是否应将该索引建为 clustered 索引。

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

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

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

20.尽量使用表变量来代替临时表。如果表变量包含大量数据,请注意索引非常有限(只有主键索引)。

21.避免频繁创建和删除临时表,以减少系统表资源的消耗。

22.临时表并不是不可使用,适当地使用它们可以使某些例程更有效,例如,当需要重复引用大型表或常用表中的某个数据集时。但是,对于一次性事件, 最好使用导出表。

23.在新建临时表时,如果一次性插入数据量很大,那么可以使用 select into 代替 create table,避免造成大量 log ,以提高速度;如果数据量不大,为了缓和系统表的资源,应先create table,然后insert。

24.如果使用到了临时表,在存储过程的最后务必将所有的临时表显式删除,先 truncate table ,然后 drop table ,这样可以避免系统表的较长时间锁定。

25.尽量避免使用游标,因为游标的效率较差,如果游标操作的数据超过1万行,那么就应该考虑改写。

26.使用基于游标的方法或临时表方法之前,应先寻找基于集的解决方案来解决问题,基于集的方法通常更有效。

27.与临时表一样,游标并不是不可使用。对小型数据集使用 FAST_FORWARD 游标通常要优于其他逐行处理方法,尤其是在必须引用几个表才能获得所需的数据时。在结果集中包括“合计”的例程通常要比使用游标执行的速度快。如果开发时 间允许,基于游标的方法和基于集的方法都可以尝试一下,看哪一种方法的效果更好。

28.在所有的存储过程和触发器的开始处设置 SET NOCOUNT ON ,在结束时设置 SET NOCOUNT OFF 。无需在执行存储过程和触发器的每个语句后向客户端发送 DONE_IN_PROC 消息。

29.尽量避免大事务操作,提高系统并发能力。

30.尽量避免向客户端返回大数据量,若数据量过大,应该考虑相应需求是否合理。

你可能不知道的MySQL

前言:

实验的数据表如下定义:
mysql> desc tbl_name;
+-------+--------------+------+-----+---------+-------+
| Field | Type         | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+-------+
| uid   | int(11)      | NO   |     | NULL    |       |
| sid   | mediumint(9) | NO   |     | NULL    |       |
| times | mediumint(9) | NO   |     | NULL    |       |
+-------+--------------+------+-----+---------+-------+
3 rows in set (0.00 sec)

存储引擎是MyISAM,里面有10,000条数据。
一、”\G”的作用

mysql> select * from tbl_name limit 1;
+--------+--------+-------+
| uid    | sid    | times |
+--------+--------+-------+
| 104460 | 291250 |    29 |
+--------+--------+-------+
1 row in set (0.00 sec)mysql> select * from tbl_name limit 1\G;
*************************** 1. row ***************************uid: 104460sid: 291250
times: 29
1 row in set (0.00 sec)

有时候,操作返回的列数非常多,屏幕不能一行显示完,显示折行,试试”\G”,把列数据逐行显示(”\G”挽救了我,以前看explain语句横向显示不全折行看起来巨费劲,还要把数据和列对应起来)。

二、”Group by”的”隐形杀手”

mysql> explain select uid,sum(times) from tbl_name group by uid\G;
*************************** 1. row ***************************id: 1select_type: SIMPLEtable: tbl_nametype: ALL
possible_keys: NULLkey: NULLkey_len: NULLref: NULLrows: 10000Extra: Using temporary; Using filesort
1 row in set (0.00 sec)mysql> explain select uid,sum(times) from tbl_name group by uid order by null\G;
*************************** 1. row ***************************id: 1select_type: SIMPLEtable: tbl_nametype: ALL
possible_keys: NULLkey: NULLkey_len: NULLref: NULLrows: 10000Extra: Using temporary
1 row in set (0.00 sec)

默认情况下,Group by col会对col字段进行排序,这就是为什么第一语句里面有Using filesort的原因,如果你不需要对col字段进行排序,加上order by null吧,要快很多,因为filesort很慢的。

三、大批量数据插入

最高效的大批量插入数据的方法:

load data infile '/path/to/file' into table tbl_name;

如果没有办法先生成文本文件或者不想生成文本文件,可以一次插入多行:

insert into tbl_name values (1,2,3),(4,5,6),(7,8,9)...

注意一条sql语句的最大长度是有限制的。如果还不想这样,可以试试MySQL的,应该都会比硬生生的逐条插入要快许多。

如果数据表有索引,建议先暂时禁用索引:

alter table tbl_name disable keys;

插入完毕之后再激活索引:

alter table tbl_name enable keys;

对MyISAM表尤其有用。避免每插入一条记录系统更新一下索引。

四、最快复制表结构方法

mysql> create table clone_tbl select * from tbl_name limit 0;
Query OK, 0 rows affected (0.08 sec)

只会复制表结构,索引不会复制,如果还要复制数据,把limit 0去掉即可。

五、加引号和不加引号区别

给数据表tbl_name添加索引:

mysql> create index uid on tbl_name(uid);

测试如下查询:

mysql> explain select * from tbl_name where uid = '1081283900'\G;
*************************** 1. row ***************************id: 1select_type: SIMPLEtable: tbl_nametype: ref
possible_keys: uidkey: uidkey_len: 4ref: constrows: 143Extra:
1 row in set (0.00 sec)

我们在整型字段的值上加索引,是可以用到索引的,网上不少人误传在整型字段上加引号无法使用索引。修改uid字段类型为varchar(12):

mysql> alter table tbl_name change uid uid varchar(12) not null;

测试如下查询:

mysql> explain select * from tbl_name where uid = 1081283900\G;
*************************** 1. row ***************************id: 1select_type: SIMPLEtable: tbl_nametype: ALL
possible_keys: uidkey: NULLkey_len: NULLref: NULLrows: 10000Extra: Using where
1 row in set (0.00 sec)

我们在查询值上不加索引,结果索引无法使用,注意安全。

六、前缀索引

有时候我们的表中有varchar(255)这样的字段,而且我们还要对该字段建索引,一般没有必要对整个字段建索引,建立前812个字符的索引应该就够了,很少有连续812个字符都相等的字段。

为什么?更短的索引意味索引更小、占用CPU时间更少、占用内存更少、占用IO更少和很更好的性能。

七、MySQL索引使用方式

MySQL在一个查询中只能用到一个索引(5.0以后版本引入了index_merge合并索引,对某些特定的查询可以用到多个索引,具体查考中文英文,所以要根据查询条件建立联合索引,联合索引只有第一位的字段在查询条件中能才能使用到。

如果MySQL认为不用索引比用索引更快的话,那么就不会用索引。

mysql> create index times on tbl_name(times);
Query OK, 10000 rows affected (0.10 sec)
Records: 10000  Duplicates: 0  Warnings: 0mysql> explain select * from tbl_name where times > 20\G;
*************************** 1. row ***************************id: 1select_type: SIMPLEtable: tbl_nametype: ALL
possible_keys: timeskey: NULLkey_len: NULLref: NULLrows: 10000Extra: Using where
1 row in set (0.00 sec)mysql> explain select * from tbl_name where times > 200\G;
*************************** 1. row ***************************id: 1select_type: SIMPLEtable: tbl_nametype: range
possible_keys: timeskey: timeskey_len: 3ref: NULLrows: 1599Extra: Using where
1 row in set (0.00 sec)

数据表中times字段绝大多数都比20大,所以第一个查询没有用索引,第二个才用到索引。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/555300.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

cheungssh mysql密码_CheungSSH安装及基本使用

CheungSSH比Ansible的使用更简单&#xff0c;尤其是配置方面&#xff01;而Ansible有的功能&#xff0c; 我的这个程序一样有&#xff0c;和Ansible一样是python开发&#xff0c; 所以跟Ansible的模式一样&#xff0c; 但是CheungSSH 操作更简单&#xff01;配置更轻量&#xf…

MySQL100万条数据的一张表,如何查询优化?

1.两种查询引擎查询速度&#xff08;myIsam 引擎 &#xff09; InnoDB 中不保存表的具体行数&#xff0c;也就是说&#xff0c;执行select count(*) from table时&#xff0c;InnoDB要扫描一遍整个表来计算有多少行。 MyISAM只要简单的读出保存好的行数即可。 注意的是&…

mysql增删改查操作语句_学习笔记-mysql增删改查操作语句

1.mysql增删改查操作语句&#xff1a;1)如果想在一个已经建好的表中添加一列&#xff0c;可以用以下代码&#xff1a;alter table t1 add column addr varchar(20) not null;2)这条语句会向已有的表t1中加入一列&#xff0c;这一列在表的最后一列位置。如果我们希望添加在指定的…

mybatis group by 分组查询:将返回结果封装为map

文章目录1. 最简单但性能最差的做法2. 使用group by分组查询&#xff0c;将查询结果封装成类3.group by分组查询&#xff0c;将结果封装为map。直接封装为map&#xff1f;List1. 最简单但性能最差的做法 在逻辑层分多次对数据库进行查询。伪代码如下。 List<String> na…

esl证明函 oracle_强弱分明 Astralis证明之战—ESL科隆B组浅析

HLTV排名前16名中的13支队伍(缺席的是G2和North)将齐聚这座坐落在莱茵河畔的城市进行厮杀&#xff0c;争夺比赛的最高荣誉。这项赛事也是继今年卡托维茨Major以来含金量最高&#xff0c;强队参赛最多的线下赛事。下面我们就来分析一下B组的出线形势。B组分组*本次比赛的赛制依旧…

关于new ArrayList()和Collections.emptyList()

很明显 new ArrayList()是创建一个Collection实例&#xff0c;它是Collection集合下面的一个实现类&#xff08;中间继承了AbstractList&#xff09;&#xff0c;它的实例有Collection的增加&#xff0c;删除&#xff0c;修改等方法&#xff0c; ArrayList平常用的很多&#x…

mysql 1418错误_mysql 1418错误原因及解决

摘自 http://blog.sina.com.cn/s/blog_6f68845001013k8a.html具体错误&#xff1a;使用mysql创建、调用存储过程&#xff0c;函数以及触发器的时候会有错误符号为1418错误。ERROR 1418 (HY000): This function has none of DETERMINISTIC, NO SQL,or READS SQL DATA in its dec…

ArrayList()和Collections.emptyList()的区别emptyList()、emptySet()、emptyMap()的作用和好处以及要注意的地方

前言 Java中ArrayList或许是我们平时开发最常用的一个集合类了&#xff0c;其次是HashMap&#xff0c;基本上满足了业务开发的绝大多数场景。今天要说的就是Collections.emptyList()和new ArrayList()的区别以及注意事项。 先来一段代码 运行main方法&#xff0c;会有如下输出…

mysql 5.6加用户_Mysql 5.6添加修改用户名和密码的方法

先登录MySQLshell> mysql --userroot mysql有密码的需要添加 –password 或-p 选项添加用户mysql>CREATE USER finleylocalhost IDENTIFIED BY some_pass;mysql>GRANT ALL PRIVILEGES ON *.* TO finleylocalhost WITH GRANT OPTION;mysql>CREATE USER finley% IDEN…

java中SimpleDateFormat线程安全问题及解决方案

最近看到一篇文章提到了SimpleDateFormat这个类。说这个类在单线程程序中没问题&#xff0c;但是在多线程环境下会线程安全的问题。 出于兴趣对这个问题进行了查证。网上有很多关于这个问题的文章&#xff0c;也解析了其中的原因。主要原因是因为SimpleDateFormat转换日期是通…

基于mysql搭建框架环境搭建_Maven+Spring+Spring MVC+MyBatis+MySQL,搭建SSM框架环境

项目建设完成之后的结构&#xff1a;数据库的表结构如下&#xff1a;环境建设&#xff1a;搭建Maven环境、Tomcat环境、需要MySql 数据库支持&#xff0c;使用的编程工具Eclipse (这些是前期准备)&#xff1b;开始创建工程&#xff1a;1.创建一个Maven工程&#xff1a;选择weba…

DataIntegrityViolationException: Error attempting to get column处理方案汇总

项目背景 项目整体采用的是springbootmybatis 方式。有一次做数据查询的时候。console突然报&#xff1a;DataIntegrityViolationException: Error attempting to get column ‘xx’…异常。起初没在意。以为是xml中的SQL写错了&#xff0c;排查了没问题。百度一下这个报错&…

mysql 查询商品列表 显示tag_让前台页面商品列表显示后台数据库中的商品

品牌&#xff1a;经销商&#xff1a;规格&#xff1a;每零售价&#xff1a;元购买日期&#xff1a;件&#xffe5;19.6&#xffe5;19.6删除实现单选&#xff0c;全选商品function checkAll(obj, name){var el document.getElementsByTagName(input);var len el.length;for (…

servlet的本质是什么,它是如何工作的?

servlet的本质是什么&#xff0c;它是如何工作的&#xff1f;基于计算机和网络通讯(主要是http协议)构建网络应用的&#xff0c;具体的实现细节是怎样的? 查看https://www.zhihu.com/question/21416727

oschina mysql limit_如何提高MySQL Limit查询的性能

在MySQL数据库操作中&#xff0c;我们在做一些查询的时候总希望能避免数据库引擎做全表扫描&#xff0c;因为全表扫描时间长&#xff0c;而且其中大部分扫描对客户端而言是没有意义的。其实我们可以使用Limit关键字来避免全表扫描的情况&#xff0c;从而提高效率。有个几千万条…

Mybatis原理:结果集封装详解

​ 经过sql参数解析、sql动态组装和执行sql&#xff0c;相对而言&#xff0c;结果集的封装&#xff0c;是mybatis数据处理的最后一环。这里只对查询结果而言&#xff0c;因为更新语句一般都是返回影响的行数。抛开mybatis&#xff0c;如果让我们组装结果&#xff0c;我们该如何…

python内置函数面向对象_Pyhton——面向对象进阶二:类的内置函数补充、描述符...

Pyhton——面向对象进阶二&#xff1a;一、类的内置函数补充1、isinstance(obj,cls)——检查obj是否是该类的对象class Hoo:def __init__(self,name,tem):self.name nameself.tem temclass foo(Hoo):passf1foo(e,20)print(isinstance(f1,Hoo))首先 f1 肯定是 foo 的对象&…

vue项目打包后部署到服务器(超详细步骤)

耽误了几天, 终于开始写第二篇博客了, 这篇会讲怎么将vue项目打包部署到服务器, 其实和上一篇的uni-app步骤一样的, 就是最后多了一步修改nginx配置, 好 , 上操作 一 ,打包项目 vscode下载链接&#xff1a;https://pan.baidu.com/s/1ibHt7XB6EZy37BDb1CigWw 提取码&#xff1…

postman怎么不登陆使用_最新百度云不限速,免安装、免登陆、不限速,打开网站就能使用...

上次给大家安利了一波Pandownload手机版/电脑版。那篇文章中也说了&#xff0c;这类应用使用不当可能会遇到账号被限速的情况&#xff0c;而且手机版必须登录才能进行不限速下载。总之&#xff0c;凡是没登录账号的小伙伴&#xff0c;下载过程会非常曲折。那么是否有无需登录就…

vue项目配置打包测试环境/生产环境

vue项目配置打包测试环境/生产环境&#xff1a; 开发环境运行命令&#xff1a;npm run serve 生产环境打包命令&#xff1a;npm run pro 测试环境打包命令&#xff1a;npm run build 步骤&#xff1a; 1.项目中添加一个配置ip的js文件&#xff0c;比如如下的ip-config.js&…