索引】从500万条数据中查询,求优化一条SQL语句

2020-05-28 09:09发布

2条回答
测试之光
1楼 · 2020-05-28 11:36.采纳回答

百万条数据快速查询优化技巧
1.应尽量避免在where子句中使用!=或<>操作符
2.应尽量避免在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
3. 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
4.下面的查询也将导致全表扫描
如:select id from t where name like ‘?c%’
若提高效率,可以考虑全文检索
5. 如果在where子句中使用参数,也会导致全表扫描。因为sql只有在运行时才会解析局部变量,但优化程序不能将访问计划的选择推迟到运行时,它必须在编译时进行选择。然而,如果在编译时建立访问计划,变量的值还是未知的,因而无法作为索引选择的输入项。如下面语句将进行全表扫描:
Select id from t where num=@num
可以改为强制查询使用索引:
Select id from t with(index(索引名)) where num=@num
6.应尽量避免在where子句中对字段进行表达式操作,这将导致引擎放弃使用而进行全表扫描。
如:select if from t where num/2=100
应改为:select id from t where num=100*2
7.应尽量避免在where子句中对字段进行函数操作,这将导致引擎放弃使用索引而进行全表扫描。
如:select id from t where substring(name,1,3)=’abc’ ----name以abc开头的id
Select id from t where datadiff(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’
8.不要在where子句中的”=”左边进行函数,算术运算或其他表达式运算,否则系统将可能无法正确使用索引
9.在使用索引字段作为条件时,如果该索引是复合索引,那么必须使用到该索引中的第一个字段作为条件时才能保证系统使用该索引,否则该索引不会被使用,并且应尽可能的让字段顺序与索引顺序相一致
10. 不要写一些没有意义的查询,如需要生成一个空表结构:
Create table #t(…)
11.很多时候用exist代替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 )
12.并不是所有索引对查询都有效,sql是根据表中数据来进行优化查询的,当索引列有大量数据重复时,sql查询可能不会利用索引,如一表中有字段sex,male,female几乎各一半,那么即使在Sex上建了索引也对查询效率起不了作用
13.索引并不是越多越好,索引固然可以提高相应的select 的效率,但同时也降低了insert及uodate的效率,因为insert或update时有可能会重建索引,所以怎样建索引需要慎重考虑,视具体情况而定。一个表的索引数最好不要超过6个,若太多则应考虑一些不常用到的列上建的索引是否愚必要
14.尽量使用数字型字段,若只含数值信息的字段尽量不要涉及为字符型,这会降低查询和连接的性能,并会增加存储开销。这是因为引擎在处理查询和连接时会逐个比较字符串中每一个字符,而对于数字型而言只需要比较一次就够了
15.尽可以的使用varchar/nvarchar代替char/nchar,因为首先变长字段存储空间小,可以节省存储空间,其次对于查询来说,在一个相对较小的字段内搜索效率显高些
16.任何地方都不要使用select * from t,用具体的字段列表代替“*”,不要返回用不到的任何字段
17.尽量使用表变量来代替临时表。如果表变量包含大量数据,请注意索引非常有限(只有主键索引)
18.避免频繁创建和删除临时表,以减少系统表资源的消耗
19.在新建临时表时,如果一次性插入数据量很大,那么可以使用select into代替create table,避免造成大量log,以提高速度,如果数据量不大,为了缓和系统表的资源,应先create table,然后insert
20.如果使用到了临时表,在存储过程的最后务必将所有的临时表显式删除,先truncate table,然后drop table,这样可以避免系统表的较长时间锁定
21.尽量避免使用游标,因为游标的效率较差,如果游标操作的数据超过1万行,那么就应该考虑改写
22.使用基于游标的方法或临时表方法之前,应先寻找基于集的解决方案来解决问题,基于集的方法通常更有效
23.与临时表一样,游标并不是不可使用。对小型数据集使用FAST_FORWARD游标通常要优于其他逐行处理方法,尤其是在必须引用几个表才能获得所需的数据时。在结果集中包括“合计”的例程通常要比使用游标执行的速度快。如果开发时间允许,基于游标的方法和基于集的方法都可以尝试一下,看哪一种方法的效果更好
24.在所有的存储过程和触发器的开始处设置SET NOCOUNT ON ,在结束时设置SET NOCOUNT OFF。无需在执行存储过程和触发器的每个语句后在客户端发送DONE_IN_PROC消息
25.尽量避免大事务操作,提高系统并发能力
26.尽量避免向客户端返回大数据量,若数据量过大,应该考虑相应需求是否合理

青皮桔味的意境
2楼 · 2021-11-17 10:51


  1. CREATE TABLE IF NOT EXISTS `jdp_tb_trade` (  

  2.   `tid` bigint(20) NOT NULL,  

  3.   `status` varchar(64) DEFAULT NULL,  

  4.   `type` varchar(64) DEFAULT NULL,  

  5.   `seller_nick` varchar(32) DEFAULT NULL,  

  6.   `buyer_nick` varchar(32) DEFAULT NULL,  

  7.   `created` datetime DEFAULT NULL,  

  8.   `modified` datetime DEFAULT NULL,  

  9.   `jdp_hashcode` varchar(128) DEFAULT NULL,  

  10.   `jdp_response` mediumtext,  

  11.   `jdp_created` datetime DEFAULT NULL,  

  12.   `jdp_modified` datetime DEFAULT NULL,  

  13.   PRIMARY KEY (`tid`),  

  14.   KEY `ind_jdp_tb_trade_seller_nick_jdp_modified` (`seller_nick`,`jdp_modified`),  

  15.   KEY `ind_jdp_tb_trade_jdp_modified` (`jdp_modified`),  

  16.   KEY `ind_jdp_tb_trade_seller_nick_modified` (`seller_nick`,`modified`),  

  17.   KEY `ind_jdp_tb_trade_modified` (`modified`)  

  18. ) ENGINE=InnoDB DEFAULT CHARSET=utf8;  








相关问题推荐

  • 回答 5

    据中国互联网络信息中心(CNNIC)发布的第43次《中国互联网络发展状况统计报告》显示,截至2018年12月,我国网民规模达8.29亿,普及率达59.6%,全年新增网民5653万。有人的地方就有互联网,有互联网的地方就有互联网营销。日常生活中,无论是衣食住行还是娱乐消...

没有解决我的问题,去提问