Mysql数据库千万级数据处理优化
- 格式:doc
- 大小:21.00 KB
- 文档页数:5
MySQL百万到千万级别数据量的优化⽅案百万级字段选择优化表字段 not null,因为 null 值很难查询优化且占⽤额外的索引空间,推荐默认数字 0。
数据状态类型的字段,⽐如 status, type 等等,尽量不要定义负数,如 -1。
因为这样可以加上 UNSIGNED,数值容量就会扩⼤⼀倍。
可以的话⽤ TINYINT、SMALLINT 等代替 INT,尽量不使⽤ BIGINT,因为占的空间更⼩。
字符串类型的字段会⽐数字类型占的空间更⼤,所以尽量⽤整型代替字符串,很多场景是可以通过编码逻辑来实现⽤整型代替的。
字符串类型长度不要随意设置,保证满⾜业务的前提下尽量⼩。
⽤整型来存 IP。
单表不要有太多字段,建议在20以内。
为能预见的字段提前预留,因为数据量越⼤,修改数据结构越耗时。
索引设计优化索引,空间换时间的优化策略,基本上根据业务需求设计好索引,⾜以应付百万级的数据量,养成使⽤ explain 的习惯,关于 explain 也可以访问:explain 让你的 sql 写的更踏实了解更多。
⼀个常识:索引并不是越多越好,索引是会降低数据写⼊性能的。
索引字段长度尽量短,这样能够节省⼤量索引空间;取消外键,可交由程序来约束,性能更好。
复合索引的匹配最左列规则,索引的顺序和查询条件保持⼀致,尽量去除没必要的单列索引。
值分布较少的字段(不重复的较少)不适合建索引,⽐如像性别这种只有两三个值的情况字段建⽴索引意义不⼤。
需要排序的字段建议加上索引,因为索引是会排序的,能提⾼查询性能。
字符串字段使⽤前缀索引,不使⽤全字段索引,可⼤幅减⼩索引空间。
查询语句优化尽量使⽤短查询替代复杂的内联查询。
查询不使⽤ select *,尽量查询带索引的字段,避免回表。
尽量使⽤ limit 对查询数量进⾏限制。
查询字段尽量落在索引上,尤其是复合索引,更需要注意最左前缀匹配。
拆分⼤的 delete / insert 操作,⼀⽅⾯会锁表,影响其他业务操作,还有⼀⽅⾯是 MySQL 对 sql 长度也是有限制的。
Mysql-Limit优化limit 查询导出优化耗时本质mysql⼤数据量使⽤limit分页,随着页码的增⼤,查询效率越低下。
当⼀个表数据有⼏百万的数据的时候成了问题!如 select * from table limit 0,10 这个没有问题当 limit 200000,10 的时候数据读取就很慢原因本质: 1)limit语句的查询时间与起始记录(offset)的位置成正⽐ 2)mysql的limit语句是很⽅便,但是对记录很多:百万,千万级别的表并不适合直接使⽤。
例如: limit10000,20的意思扫描满⾜条件的10020⾏,扔掉前⾯的10000⾏,返回最后的20⾏,问题就在这⾥。
LIMIT 2000000, 30 扫描了200万+ 30⾏,怪不得慢的都堵死了,甚⾄会导致磁盘io 100%消耗。
但是: limit 30 这样的语句仅仅扫描30⾏。
优化⼿段⼲掉或者利⽤ limit offset,size 中的offset不是直接使⽤limit,⽽是⾸先获取到offset的id然后直接使⽤limit size来获取数据对limit分页问题的性能优化⽅法利⽤表的覆盖索引来加速分页查询覆盖索引:就是select 的数据列只⽤从索引中就能获得,不必读取数据⾏。
mysql 可以利⽤索引返回select列表中的字段,⽽不必根据索引再次读取数据⽂件,换句话说:查询列要被所创建的索引覆盖因为利⽤索引查找有优化算法,且数据就在查询索引上⾯,不⽤再去找相关的数据地址了,这样节省了很多时间。
另外Mysql中也有相关的索引缓存,在并发⾼的时候利⽤缓存就效果更好了。
在我们的例⼦中,我们知道id字段是主键,⾃然就包含了默认的主键索引。
这次我们之间查询最后⼀页的数据(利⽤覆盖索引,只包含id列),如下:#覆盖索引只包含id列的时间显著优于select*不⾔⽽喻select*from order_table where company_id =1and mark =0order by id desc limit 200000 ,20;select id from order_table where company_id =1and mark =0order by id desc limit 200000 ,20;那么如果我们也要查询所有列,有两种⽅法,⼀种是id>=的形式,另⼀种就是利⽤join,看下实际情况:#两者⽤的都是⼀个原理嘛,所以效果也差不多SELECT*FROM xxx WHERE ID >=(select id from xxx limit 1000000, 1) limit 20;SELECT*FROM xxx a JOIN (select id from xxx limit 1000000, 20) b ON a.ID = b.id;环境准备1. test_dev.order_table 300万数据2. test_begin.order_table 5000万数据环境差异:两边表结构->索引不⼀样,会存再同样查询前20万数据 test_begin ⽐ test_dev 快些实战1:数据量百万级别利⽤或使⽤ offset#show profiles 分析性能#临时开启SET profiling =1;#查询时候以⾮缓存⽅式查询验证:select SQL_NO_CACHE ......#20-40万:1255907360-80万:12159073160-180万:11159073260-280万:10158757#含 offset 查询->平均耗时:9.958s 左右select SQL_NO_CACHE *from order_table where company_id =1and mark =0order by id desc limit 200000 ,200000;#分开查询先查询最⼤id 在执⾏ id<=max的效率性能与合在⼀起⼏乎⼀致#平均耗时:7.505s 左右select id from order_table where company_id =1and mark =0order by id desc limit 200000 ,1;#平均耗时:9.092s 左右select*from order_table where company_id =1and mark =0and id <=12559073order by id desc limit 200000;#覆盖索引获取max => id<=max->平均耗时:17.576s 左右select SQL_NO_CACHE *from order_table where company_id =1and mark =0and id <= (select id from order_table where company_id =1and mark =0order by id desc limit 200000 ,1) order by id desc limit 200000; #覆盖索引+join->平均耗时:11.325s 左右select SQL_NO_CACHE p.*from order_table p join (select id from order_table where company_id =1and mark =0order by id desc limit 200000 ,200000) a on a.id = p.id;性能分析说明show profile CPU,SWAPS,BLOCK IO,MEMORY,SOURCE for query 520;⽅式1.limit offset,size(含⼦查询)20-40万60-80万160-180万260-280万⽅式2.id < max and limit sizeps: 实战中可以直接将上⼀页的最⼩id 传⼊到下⼀页查询中当max使⽤,从⽽节省⼦查询的消耗。
(转)优化GroupBy--MYSQL⼀次千万级连表查询优化概述:交代⼀下背景,这算是⼀次项⽬经验吧,属于公司⼀个已上线平台的功能,这算是离职⼈员挖下的坑,随着数据越来越多,原本的SQL查询变得越来越慢,⽤户体验特别差,因此SQL优化任务交到了我⼿上。
这个SQL查询关联两个数据表,⼀个是攻击IP⽤户表主要是记录IP的信息,如第⼀次攻击时间,地址,IP等等,⼀个是IP攻击次数表主要是记录每天IP攻击次数。
⽽需求是获取某天攻击IP信息和次数。
(以下SQL语句测试均在测试服务器上上,正式服务器的性能好,查询时间快不少。
)准备:查看表的⾏数:未优化前SQL语句为:SELECTattack_ip,country,province,city,line,info_update_time AS attack_time,sum( attack_count ) AS attack_timesFROM`blacklist_attack_ip`INNER JOIN `blacklist_ip_count_date` ON `blacklist_attack_ip`.`attack_ip` = `blacklist_ip_count_date`.`ip`WHERE`attack_count` > 0AND `date` BETWEEN '2017-10-13 00:00:00'AND '2017-10-13 23:59:59'GROUP BY`ip`LIMIT 10 OFFSET 1000123456789101112131415161718先EXPLAIN分析⼀下:这⾥看到索引是有的,但是IP攻击次数表blacklist_ip_count_data也⽤上了临时表。
那么这SQL不优化直接第⼀次执⾏需要多久(这⾥强调第⼀次是因为MYSQL带有缓存功能,执⾏过⼀次的同样SQL,第⼆次会快很多。
Mysql千万级别数据优化方案目录目录 (1)一、目的与意义 (1)1) 说明 (1)二、解决思路与根据(本测试表中数据在千万级别) (2)1) 建立索引 (2)2) 数据体现(主键非索引,实际测试结果其中fid建立索引) (2)3) MySQL分页原理 (2)4) 经过实际测试当对表所有列查询时 (3)三、总结 (3)1) 获得分页数据 (3)2) 获得总页数:创建表记录大数据表中总数通过触发器来维护 (3)一、目的与意义1)说明在MySql单表中数据达到千万级别时数据的分页查询结果时间过长,对此进行优达到最优效果,也就是时间最短;(此统计利用的jdbc连接,其中fid为该表的主键;)二、解决思路与根据(本测试表中数据在千万级别)1)建立索引优点:当表中有大量记录时,若要对表进行查询,第一种搜索信息方式是全表搜索,是将所有记录一一取出,和查询条件进行一一对比,然后返回满足条件的记录,这样做会消耗大量数据库系统时间,并造成大量磁盘I/O操作;第二种就是在表中建立索引,然后在索引中找到符合查询条件的索引值,最后通过保存在索引中的ROWID(相当于页码)快速找到表中对应的记录。
缺点:当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,降低了数据的维护速度。
2)数据体现(主键非索引,实际测试结果其中fid建立索引)未创建索引:SELECT fid from t_history_data LIMIT 8000000,10 结果:13.396s创建索引:SELECT fid from t_history_data LIMIT 8000000,10 结果:2.896sselect * from t_history_data where fid in ( 任意十条数据的id ) 结果:0.141s首先通过分页得到分页的数据的ID,将ID拼接成字符串利用SQL语句select * from table where ID in (ID字符串)此语句受数据量大小的影响比较小(如上测试);3)MySQL分页原理MySQL的limit工作原理就是先读取n条记录,然后抛弃前n条,读m条想要的,所以n越大,性能会越差。
mysql sql 百万级数据库优化方案 2010-04-25 编辑:kp12345 我要投递文章稿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=03.应尽量避免在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=205.in 和not in 也要慎用,否则会导致全表扫描,如:select id from t where num in(1,2,3)对于连续的数值,能用between 就不要用in 了:select id from t where num between 1 and 36.下面的查询也将导致全表扫描: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 子句中对字段进行表达式操作,这将导致引擎放弃使用索引而进行全表扫描。
MySQL对于千万级的⼤表要怎么优化?千万级,MySQL实际上确实不是什么压⼒,InnoDB的存储引擎,使⽤的是B+树存储结构,千万级的数据量,基本也就是三到四层的搜索,如果有合适的索引,性能基本也不是问题。
但经常出现的情况是,业务上⾯的增长,导致数据量还会继续增长,为了应对这⽅⾯的问题⽽必须要做扩展了此时可能⾸先需要考虑的就是分表策略了。
当然分表,可能还有其它⼏个原因,⽐如表变⼤了,千万级的数据库,为了减少运维成本,降低风险,就想到了通过分表来解决问题,这都是⽐较合适的。
分表,还有另⼀个⽅⾯的意思,就是在数据量更⼤的情况下,为了分担业务压⼒,将数据表分到不同的实例中去,这样有两⽅⾯的好处:1. 降低业务风险,如果⼀套数据库集群出问题了,那⾄少还有其它的可以服务,这样被影响的业务可能只是⼀部分。
2. 降低运维成本,如果数据库想要做迁移,或者正常维护等操作了,那涉及到的数据量⼩,下线时间短,操作快,从⽽对业务影响也就⼩了。
这种⽅式,我们称之为“分实例”。
分表的话,还是要根据具体的业务逻辑等⽅⾯来做,这⽅⾯有更精彩的回答,我这⾥贴⼀下:========================================分库分表是MySQL永远的话题,⼀般情况下认为MySQL是个简单的数据库,在数据量⼤到⼀定程度之后处理查询的效率降低,如果需要继续保持⾼性能运转的话,必须分库或者分表了。
关于数据量达到多少⼤是个极限这个事⼉,本⽂先不讨论,研究源码的同学已经证实MySQL或者Innodb内部的锁粒度太⼤的问题⼤⼤限制了MySQL提供QPS的能⼒或者处理⼤规模数据的能⼒。
在这点上,⼀般的使⽤者只好坐等官⽅不断推出的优化版本了。
在⼀般运维的⾓度来看,我们什么情况下需要考虑分库分表?⾸先说明,这⾥所说的分库分表是指把数据库数据的物理拆分到多个实例或者多台机器上去,⽽不是类似分区表的原地切分。
原则零:能不分就不分。
Mysql⼤数据量查询优化思路详析⽬录1. 千万级别⽇志查询的优化2. ⼏百万⿊名单库的查询优化3. Mybatis批量插⼊处理问题项⽬场景:Mysql⼤表查询优化,理论上千万级别以下的数据量Mysql单表查询性能处理都是可以的。
问题描述:在我们线上环境中,出现了mysql⼏千万级别的⽇志查询、⼏百万级别的⿊名单库查询分页查询及条件查询都慢的问题,针对Mysql表优化做了⼀些优化处理。
原因分析:⾸先说⼀下⽇志查询,在Mysql中如果索引加的⽐较合适,⾛索引情况下千万级别查询不会超过⼀秒,Mysql查询的速度和检索的数据条数有关。
在Mybatis中,分页查询是先执⾏Count记录总数,再执⾏limit a,b 的⽅式来进⾏的,⽽Mysql的Count计数⽅式是将所有的数据过滤⼀遍进⾏累加,因此当⽇志表数据过千万时,统计⼀次就是⼗⼏秒钟的时间(这⾥是服务器环境,本地情况下甚⾄是⼏分钟)。
limit a,b的⽅式也⼀样,Mysql查询时会先⼀条⼀条数到第a条,然后向后再数b条作为查询结果,因此当起始⾏数越来越⼤时查询同样会变得很慢,也就是当你点第⼀页时可能⼀下就查出来了,当你点最后⼀页的时候可能⼏⼗秒才能查出来。
⿊名单库查询优化同理,也是需要通过条件优化。
在进⾏⼤批量数据落库时,使⽤的Mybatis批量插⼊,发现当批次数据超过3000时速度会急剧变慢,这是⼀个Mybatis娘胎⾥⾃带的问题,也需要进⾏解决。
解决⽅案:这⾥只简单说明优化的⼏个⽅向。
1. 千万级别⽇志查询的优化1. ⾸先说下⽇志查询,重点是优化⽆条件是分页查询,在⽆条件时,不使⽤MyBatis的分页插件,⽽是⾃⼰⼿写⼀个分页查询,由于MySql的count耗时过长,我们先优化他。
2. 优化Count:⽇志表的数据只增,不会出现中间某条删除,所以他的数据可以理解成是连续的,我们可以在内存中直接进⾏计数,记录count总数,或者给表添加⼀个⾃增的ID字段,直接select max(id)就是总数量,这样count查询的效率会提升到毫秒级别。
记⼀次mysql千万订单汇总查询优化正⽂公司订单系统每⽇订单量庞⼤,有很多表数据超千万。
公司SQL优化这块做的很不好,可以说是没有做,所以导致查询很慢。
节选某个功能中的⼀句SQL EXPLAIN查看执⾏计划,EXPLAIN + SQL 查看SQL执⾏计划⼀个索引没⽤到,受影响⾏接近2000万,难怪会慢。
原来的SQL打印出来估计有好⼏张A4纸,我发个整理后的简版。
SELECT COUNT(t.w_order_id) lineCount, SUM(ROUND(t.feel_total_money / 100, 2)) AS lineTotalFee, SUM(ROUND(t.feel_fact_money / 100, 2)) AS lineFactFeeFROM w_orders_his tWHERE 1=1 AND DATE_FORMAT(t.create_time, '%Y-%m-%d') >= STR_TO_DATE(#{beginTime},'%Y-%m-%d') AND DATE_FORMAT(t.create_time, '%Y-%m-%d') <= STR_TO_DATE(#{endTime},'%Y-%m-%d') AND t.pay_state = #{payState} AND t.store_id LIKE '%#{storeId}%' limit 0,10这条sql需求是在两千万的表中捞出指定时间和条件的订单进⾏总数总⾦额汇总处理。
优化sql需要根据公司的业务,技术的架构等,且针对不同业务每条SQL的优化都是有差异的。
优化点1:AND DATE_FORMAT(t.create_time, '%Y-%m-%d') >= STR_TO_DATE(#{beginTime},'%Y-%m-%d')AND DATE_FORMAT(t.create_time, '%Y-%m-%d') <= STR_TO_DATE(#{endTime},'%Y-%m-%d')我们知道sql中绝对要减少函数的使⽤,像左边DATE_FORMAT(t.create_time, '%Y-%m-%d') 是绝对禁⽌使⽤的,如果数据库有⼀百万数据那么就会执⾏⼀百万次函数,⾮常⾮常影响效率。
记⼀次MySql千万级数据量单表按⽇分组查询平均值的优化遇到
的各种问题
1、单表千万级数据量⼦查询 where in 要⽐ where exists 快(亲测查询时间差了100倍)
2、需要对datetime类型进⾏group by时(众所周知,函数不⾛索引),把⽇期的值拆分,⽐如要按⽇进⾏分组,拆分成年、⽉、⽇字段,类型分别⽤smallint、tinyint、tinyint,建⽴复合索引(Year,Month,Day)
3、数据量不⼤的临时表的存储引擎⽤engine=MEMORY ,优化效果很明显。
数据量太⼤的不建议,因为很吃内存,内存不够数据可能会丢失数据或者中断存储过程
4、truncate是先执⾏drop操作,然后再执⾏create操作,执⾏完成后会恢复初始的表空间。
(找资料时看到有⽂章说对于临时表要先truncate再drop,差点被坑死,故有此⼀记)
-------------------------------------------后续------------------------------------------------------
到⽣产环境给表加索引后,过了⼀晚数据库出故障⾃动关闭了。
正在查找原因。
原因⼤概找到了,有⼀个作业每10分钟跑⼀次,作⽤是从千万级数据量单表处查询数据然后插⼊到另⼀个表,这个作业跑⼀次耗时⼤于40分钟,跑到中途还报错退出了。
然后千万级数据量单表添加字段后也没有初始化好,添加索引的字段存在null值,导致死锁的发⽣。
不断被阻塞,最后导致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=10
union all
select 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 ‘�c%’
若要提高效率,可以考虑全文检索。
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开头的id
select id from t where datediff(day,createdate,’2005-11-30′)=0–‘2005-11-30’生成的id
应改为:
select id from t where name l ike ‘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.尽量避免大事务操作,提高系统并发能力。
sql优化方法
使用索引来更快地遍历表。
缺省情况下建立的索引是非群集索引,但有时它并不是最佳的。
在非群集索引下,数据在物理上随机存放在数据页上。
合理的索引设计要建立在对各种查询的分析和预测上。
一般来说:
a.有大量重复值、且经常有范围查询( > ,< ,> =,< =)和order by、group by 发生的列,可考虑建立群集索引;
b.经常同时存取多列,且每列都含有重复值可考虑建立组合索引;
c.组合索引要尽量使关键查询形成索引覆盖,其前导列一定是使用最频繁的列。
索引虽有助于提高性能但不是索引越多越好,恰好相反过多的索引会导致系统低效。
用户在表中每加进一个索引,维护索引集合就要做相应的更新工作。
2、在海量查询时尽量少用格式转换。
3、ORDER BY和GROPU BY:使用ORDER BY和GROUP BY短语,任何一种索引都有助于SELECT的性能提高。
4、任何对列的操作都将导致表扫描,它包括数据库教程、函数、计算表达式等等,查询时要尽可能将操作移至等号右边。
5、IN、OR子句常会使用工作表,使索引失效。
如果不产生大量重复值,可以考虑把子句拆开。
拆开的子句中应该包含索引。
6、只要能满足你的需求,应尽可能使用更小的数据类型:例如使用MEDIUMINT代替INT
7、尽量把所有的列设置为NOT NULL,如果你要保存NULL,手动去设置它,而不是把它设为默认值。
8、尽量少用VARCHAR、TEXT、BLOB类型
9、如果你的数据只有你所知的少量的几个。
最好使用ENUM类型。