SQL 语句优化

Sql语句的优化以及Sql语句优化工具 这周在做项目的时候,发现有些Sql语句写的复杂,一个复杂的Sql语句不仅性能比较低下,当涉及到重构的时候也是不容易理解和读懂的,并且一个复杂的sql语句会显著增加程序的耦合度,所以Sql语句的优化就显的很必要了。 Sql语句复杂化的原因 首先列举一下Sql语句复杂化的原因: 将业务逻辑由Sql语句实现 数据库表的设计不符合第三范式 Sql语句中含有大量冗余的不必要逻辑 没有很好的利用视图 如何优化Sql语句呢 不要超过5个表以上的连接 超过5张表以上的连接会大大增加sql引擎的消耗。 考虑使用临 阅读详情

MySQL 策略优化

索引(Index)

一、优化细则

  1. 在 where 子句中使用 != 或 <> 操作符,会导致引擎放弃使用索引而进行全表扫描。SQL 中不等于操作符会限制索引,造成全表扫描,即使比较的字段上有索引。

模糊查询效率很低原因:like 本身效率就比较低,应该尽量避免查询条件使用 like。对于like‘%...%’全模糊查询,是无法使用索引的,全表扫描自然效率很低。另外,由于匹配算法的关系,模糊查询的字段长度越大,模糊查询效率越低。
解决办法:首先尽量避免模糊查询,如果业务需要必须模糊查询,则至少保证不使用全模糊查询,【右模糊查询like ‘…%’会使用索引;左模糊like‘%...’无法直接使用索引】,但可以利用 reverse + function index 的形式,变化成 like ‘…%’。全模糊查询无法优化,不然考虑用搜索引擎。出于降低数据库服务器负载的考虑,尽可能的减少数据库模糊查询。

  1. 注意范围查询语句
    对于联合索引来说,如果存在范围查询,比如 between、>、< 等条件时,会造成后面的索引字段失效。

  2. 对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。如果排序字段没有用到索引,就尽量少排序。根据实际情况进行调整,因为有时索引太多也会降低性能。

  • order by 的列尽量被索引。order by 的列如果被索引,性能也会更好
  • 不使用 order by rand() limit ~MySQL 的随机抽取实现方法
select id from table order by rand() limit 1000;

上面的 SQL 语句,可优化为:

select id from table  t1 
join  (select rand() * (select max(id) from table ) as nid) t2 on t1.id > t2.nid
limit 1000;
  1. 在 where 子句中对字段进行 null 值判断,会导致引擎放弃使用索引而进行全表扫描,如:

理由:并不是说使用了 is null 或者 is not null 就不走索引了,这个跟MySQL版本以及查询成本都有关。如果 MySQL 优化器发现,走索引比不走索引成本还要高,肯定会放弃索引,这些条件【!=、>、is null、is not null】经常被认为使索引失效,其实是因为一般情况下,查询的成本高,优化器自动放弃索引的。如果把 null 值,换成默认值,很多时候让走索引成为可能,同时,表达意思会相对清晰一点。【见第21点】

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

  1. 在 where 子句中对字段进行函数、算术运算或其他表达式运算,会导致引擎放弃使用索引而进行全表扫描。如:

算术运算

函数操作

  1. 为列选择合适的数据类型,而且要避免隐式类型转换
  • where 子句中出现 column 字段的类型和传入的参数类型不一致时会发生类型转换,建议先确定 where 中的参数类型。
  • 能用 TINYINT 就不用 SMALLINT,能用 SMALLINE 就不用 INT,磁盘和内存消耗越小越好。

【如果字段类型是字符串,where 时一定用引号括起来,否则索引失效】
反例:

select * from user where userid = 123; 

正例:

select * from user where userid = '123'; 

为什么第一条语句未加单引号就不走索引了?这是因为不加单引号时,是字符串跟数字的比较,它们类型不匹配,MySQL 会做隐式的类型转换,把它们转换为浮点数再做比较。

  1. 结果集允许重复的话,尽量用 union all 代替 union
    union 和 union all 的差异,主要是前者不管检索结果有没有重复,都会尝试进行合并,然后在输出最终结果前进行排序、过滤操作,增加大量的 CPU 运算,加大资源消耗及延迟。而UNINON ALL 不去重,效率高于 UNION。当然,union all 的前提条件是两个结果集没有重复数据。或者结果集允许重复的话,尽量使用 union all 代替 union 。

  2. 如果限制条件中其他字段没有索引,尽量少用 or。or 两边的字段中,如果有一个不是索引字段,而其他条件也不是索引字段,会造成该查询不走索引的情况。应尽量避免在 where 子句中使用 or 来连接条件,否则将导致引擎放弃使用索引而进行全表扫描。很多时候使用 union all 或者是 union(必要的时候)的方式来代替“or”会得到更好的效果。新建一个 user 表,它有一个普通索引 userId,表结构如下:

CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `userId` int(11) NOT NULL,
  `age` int(11) NOT NULL,
  `name` varchar(255) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_userId` (`userId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

查询 userId 为 1 或者年龄为 18 岁的用户:
反例:

select * from user where userid=1 or age =18

正例:

//使用union all 
select * from user where userid=1 
union all 
select * from user where age = 18

//或者分开两条sql写:
select * from user where userid=1
select * from user where age = 18
理由:使用 or 可能会使索引失效,从而全表扫描。

对于 or+ 没有索引的 age 这种情况,假设它走了 userId 的索引,但是走到 age 查询条件时,它还得全表扫描,也就是需要三步过程:全表扫描+索引扫描+合并,如果它一开始就走全表扫描,直接一遍扫描就完事。MySQL 优化器出于效率与成本考虑,遇到 or 条件,索引可能失效,看起来也合情合理。

  1. 将大的 delete,update 或者 insert 查询变成多个小查询
    为了更优的性能以及更好的数据控制,应该将大的 sql 写成多个小查询。避免同时修改或删除过多数据,因为会造成 CPU 利用率过高,从而影响别人对数据库的访问。

反例:

//一次删除10万或者100万+?
delete from user where id <100000;
//或者采用单一循环操作,效率低,时间漫长
for(User user:list){
   delete from user; 
}

正例:

//分批进行删除,如每次500
delete user where id<500
delete product where id>=500 and id<1000;

理由:一次性删除太多数据,可能会有lock wait timeout exceed的错误,所以建议分批操作。

【关于 delete 优化】一个 delete 语句执行了2个多小时了,还没执行完,能不能把这个 SQL 回滚?答案是不能,如果直接回滚,结果会更惨。可以执行“show engine innodb status\G”,查询执行时间。如果没有运行状态,就可以 Kill 掉。

  1. 如果插入数据过多,考虑批量插入

反例:

for(User u :list){
 insert into user(name,age) values(#name#,#age#)   
}

正例:

//一次500批量插入,分批进行
insert into user(name,age) values
<foreach collection="list" item="item" index="index" separator=",">
    (#{item.name},#{item.age})
</foreach>

理由:批量插入性能好,更加省时间。
打个比喻:假如需要搬一万块砖到楼顶。有一个电梯,电梯一次可以放适量的砖(最多放 500),可以选择一次运送一块砖,也可以一次运送 500 块砖,哪个时间消耗大?

  1. select 务必指明字段,尽量避免“select * ”。因为它会进行全表扫描,不能有效利用索引,增加很多不必要的消耗(CPU、IO、内存、网络带宽),增大了数据库服务器的负担,以及它与应用程序客户端之间的网络 IO 开销。而且当表结构发生改变时,前端也需要更新。

  2. Inner join、left join、right join,优先使用 Inner join。如果是 left join,左边表结果尽量小。Inner join 内连接,在两张表进行连接查询时,只保留两张表中完全匹配的结果集。left join 在两张表进行连接查询时,会返回左表所有的行,即使在右表中没有匹配的记录。right join 在两张表进行连接查询时,会返回右表所有的行,即使在左表中没有匹配的记录。满足需求的前提下,优先使用 Inner join(内连接),如果要使用 left join,左边表数据结果尽量小,如果有条件的尽量放到左边处理。

  • MySQL 中没有 full join,可以用以下方式来解决:
select * from A 
left join B on B.name = A.name where B.name is null
union all 
select * from B;
  • 尽量使用inner join,避免left join:
    参与联合查询的表至少为2张表,一般都存在大小之分。如果连接方式是inner join,在没有其他过滤条件的情况下MySQL会自动选择小表作为驱动表;但是left join在驱动表的选择上遵循的是左边驱动右边的原则,即left join左边的表名为驱动表。
  • 合理利用索引:
    被驱动表的索引字段作为on的限制字段。
  • 利用小表去驱动大表
    从原理图能够直观的看出如果能够减少驱动表的话,减少嵌套循环中的循环次数,以减少 IO总量及CPU运算的次数。
  • 巧用STRAIGHT_JOIN:
    inner join是由MySQL选择驱动表,但是有些特殊情况需要选择另个表作为驱动表,比如有group by、order by等「Using filesort」、「Using temporary」时。STRAIGHT_JOIN来强制连接顺序,在STRAIGHT_JOIN左边的表名就是驱动表,右边则是被驱动表。在使用STRAIGHT_JOIN有个前提条件是该查询是内连接,也就是inner join。其他链接不推荐使用STRAIGHT_JOIN,否则可能造成查询结果不准确。
    这个方式有时能减少3倍的时间。

反例:

select * from tab a left join tab1 b on a.size = b.size where a.id>2; 

正例:

select * from (select * from tab where id >2) a left join tab1 b on a.size = b.size; 

理由如下:
如果 inner join 是等值连接,或许返回的行数比较少,所以性能相对会好一点。
同理,使用了左连接,左边表数据结果尽量小,条件尽量放到左边处理,意味着返回的行数可能比较少。

【不要有超过 5 个以上的表连接】连表越多,编译的时间和开销也就越大。把连接表拆开成较小的几个执行,可读性更高。如果一定需要连接很多表才能得到数据,那么意味着设计非常糟糕。

  1. SQL语句中 in 和 not in 也要慎用,否则会导致全表扫描。MySQL对于in做了相应的优化,即将in中的常量全部存储在一个数组里面,而且这个数组是排好序的。但是如果数值较多,产生的消耗也是比较大的。对于连续的数值,能用between就不要用in,再或者使用连接来替换。

  1. 区分 in 和 exists、not in 和not exists

区分 in 和 exists 主要是造成了驱动顺序的改变(这是性能变化的关键)。如果是exists,那么以外层表为驱动表,先被访问;如果是IN,那么先执行子查询。所以IN适合于外表大而内表小的情况;exists适合于外表小而内表大的情况。

关于 not in 和 not exists,推荐使用not exists,不仅仅是效率问题,not in 可能存在逻辑问题。如何高效的写出一个替代 not exists 的SQL语句?

原SQL语句:

select colname … from tableA 
where a.id not in (select b.id from tableB)

高效的SQL语句:

select colname … from tableA 
left join tableB on a.id = b.id 
where b.id is null

取出的结果集为A表不在B表中的数据。

【exist&in 的合理利用】

假设表 A 表示某企业的员工表,表B表示部门表,查询所有部门的所有员工,很容易有以下 SQL:

select * from A where deptId in (select deptId from B);

这样写等价于:

先查询部门表B
select deptId from B
再由部门deptId,查询A的员工
select * from A where A.deptId = B.deptId

可以抽象成这样的一个循环:

List<> resultSet ;
    for(int i=0;i<B.length;i++) {
          for(int j=0;j<A.length;j++) {
          if(A[i].id==B[j].id) {
             resultSet.add(A[i]);
             break;
          }
       }
    }

显然,除了使用 in,也可以用 exists 实现一样的查询功能,如下:

select * from A where exists (select 1 from B where A.deptId = B.deptId);

因为 exists 查询的理解就是,先执行主查询,获得数据后,再放到子查询中做条件验证,根据验证结果(true 或者 false),来决定主查询的数据结果是否得意保留。那么,这样写就等价于:

select * from A 先从A表做循环
select * from B where A.deptId = B.deptId 再从B表做循环。

同理,可以抽象成这样一个循环:

List<> resultSet;
    for(int i=0;i<A.length;i++) {
          for(int j=0;j<B.length;j++) {
          if(A[i].deptId==B[j].deptId) {
             resultSet.add(A[i]);
             break;
          }
       }
    }

数据库最费劲的就是跟程序链接释放。假设链接了两次,每次做上百万次的数据集查询,查完就走,这样就只做了两。相反建立了上百万次链接,申请链接释放反复重复,这样系统就受不了了。

即 MySQL 优化原则,就是小表驱动大表,小的数据集驱动大的数据集,从而让性能更优。因此,我们要选择最外层循环小的,也就是,如果 B 的数据量小于 A,适合使用 in,如果 B 的数据量大于 A,即适合选择 exist。

  1. 【推荐】in操作能避免则避免,若实在避免不了,需要仔细评估in后边的集合元素数量,控制在1000个之内。

  2. 给整型字段设置长度并无意义,int(1)与int(11)通常情况下没有任何区别。

  3. 必要时可以使用force index来强制查询走某个索引
    有的时候MySQL优化器采取它认为合适的索引来检索SQL语句,但是可能它所采用的索引并不是我们想要的。这时就可以采用force index来强制优化器使用我们制定的索引。

  4. 【强制】不要使用count(列名)或count(常量)来替代count(*),count(*)是SQL92定义的标准统计行数的语法,跟数据库无关,跟NULL和非NULL无关。

说明:count(*)会统计值为NULL的行,而count(列名)不会统计此列为NULL值的行。

  1. 不要写一些没有意义的查询,如需要生成一个空表结构:
    select col1,col2 into #t from t where 1=0
    这类代码不会返回任何结果集,但是会消耗系统资源的,应改成这样:
    create table #t(…)

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

  3. 索引并不是越多越好

  • 索引并不是越多越好,索引虽然提高了查询的效率,但是也降低了插入和更新的效率。
  • insert 或 update 时有可能会重建索引,所以建索引需要慎重考虑,视具体情况来定。
  • 一个表的索引数最好不要超过 6 个,若太多需要考虑一些索引是否没有存在的必要。
  1. 应尽可能的避免更新 clustered 索引数据列,因为 clustered 索引数据列的顺序就是表记录的物理存储顺序,一旦该列值改变将导致整个表记录的顺序的调整,会耗费相当大的资源。若应用系统需要频繁更新 clustered 索引数据列,那么需要考虑是否应将该索引建为 clustered 索引。

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

反例:

king_id` varchar(20) NOT NULL COMMENT '守护者Id'

正例:

`king_id` int(11) NOT NULL COMMENT '守护者Id'`
  1. 尽可能的使用 varchar/nvarchar 代替 char/nchar 。变长字段存储空间小,可以节省存储空间。其次对于查询来说,在一个相对较小的字段内搜索效率显然要高些。

反例:

`deptName` char(100) DEFAULT NULL COMMENT '部门名称' 

正例:

`deptName` varchar(100) DEFAULT NULL COMMENT '部门名称' 
  1. 尽量使用表变量来代替临时表。如果表变量包含大量数据,请注意索引非常有限(只有主键索引)。

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

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

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

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

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

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

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

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

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

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

  12. 使用EXPLAIN分析 SQL 计划。EXPLAIN可以检查索引使用情况以及扫描的行。日常开发写 SQL 的时候,尽量养成用 explain 分析 SQL 的习惯,尤其是走不走索引这一块。

  13. 慎用 distinct 关键字

distinct 关键字一般用来过滤重复记录,以返回不重复的记录。在查询一个字段或者很少字段的情况下使用时,给查询带来优化效果。但是在字段很多的时候使用,却会大大降低查询效率。

反例:

select distinct * from user; 

正例:

select distinct name from user; 

理由:带 distinct 的语句 CPU 时间和占用时间都高于不带 distinct 的语句。因为当查询很多字段时,如果使用 distinct,数据库引擎就会对数据进行比较,过滤掉重复数据,然而这个比较、过滤的过程会占用系统资源,CPU 时间。

【强制】count(distinct col) 计算该列除NULL之外的不重复行数,注意 count(distinct col1, col2) 如果其中一列全为NULL,那么即使另一列有不同的值,也返回为0。

  1. 【强制】当某一列的值全是NULL时,count(col)的返回结果为0,但sum(col)的返回结果为NULL,因此使用sum()时需注意NPE问题。

正例:可以使用如下方式来避免sum的NPE问题:SELECT IF(ISNULL(SUM(g)),0,SUM(g)) FROM table;

  1. 【强制】使用ISNULL()来判断是否为NULL值。

说明:NULL与任何值的直接比较都为NULL。

1) NULL<>NULL的返回结果是NULL,而不是false。

2) NULL=NULL的返回结果是NULL,而不是true。

3) NULL<>1的返回结果是NULL,而不是true。

  1. 【强制】不得使用外键与级联,一切外键概念必须在应用层解决。

说明:以学生和成绩的关系为例,学生表中的student_id是主键,那么成绩表中的student_id则为外键。如果更新学生表中的student_id,同时触发成绩表中的student_id更新,即为级联更新。外键与级联更新适用于单机低并发,不适合分布式、高并发集群;级联更新是强阻塞,存在数据库更新风暴的风险;外键影响数据库的插入速度。

  1. 【强制】禁止使用存储过程,存储过程难以调试和扩展,更没有移植性。

  2. 【强制】数据订正(特别是删除、修改记录操作)时,要先select,避免出现误删除,确认无误才能执行更新语句。

  3. 【参考】如果有国际化需要,所有的字符存储与表示,均以utf-8编码,注意字符统计函数的区别。

说明:
SELECT LENGTH(“轻松工作”); 返回为12
SELECT CHARACTER_LENGTH(“轻松工作”); 返回为4

如果需要存储表情,那么选择utf8mb4来进行存储,注意它与utf-8编码的区别。

  1. 【参考】 TRUNCATE TABLE 比 DELETE 速度快,且使用的系统和事务日志资源少,但TRUNCATE无事务且不触发trigger,有可能造成事故,故不建议在开发代码中使用此语句。 说明:TRUNCATE TABLE 在功能上与不带 WHERE 子句的 DELETE 语句相同。

  2. 为获得相同结果集的多次执行,请保持SQL语句前后一致。这样做的目的是为了充分利用查询缓冲。比如根据地域和产品ID查询产品价格,第一次使用了:
    select price from order where id='123' and region='BEIJING'
    那么第二次同样的查询,请保持以上语句的一致性,比如不要将where语句里面的id和region位置调换顺序。

  3. 为了提高 group by 语句的效率,可以在执行到该语句前,把不需要的记录过滤掉。

反例:

select job,avg(salary) from employee
group by job 
having job ='president' or job = 'managent'

正例:

select job,avg(salary) from employee
where job ='president' or job = 'managent' 
group by job
  1. 索引不会包含有 NULL 值的列
    只要列中包含有 NULL 值都将不会被包含在索引中,复合索引中只要有一列含有 NULL 值,那么这一列对于此复合索引就是无效的。所以在数据库设计时不能让字段的默认值为 NULL。

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

  3. 字符字段只建前缀索引

  4. 字符字段最好不要做主键

  5. 尽量不用UNIQUE,由程序保证约束

  6. 明知只有一条查询结果,那请使用 “LIMIT 1”

“LIMIT 1”可以避免全表扫描,找到对应结果就不会再继续扫描了。

  1. varchar应给设置一个合适的长度而不是给一个很大的长度,因为MySQL建立索引时一般会默认使用的该字段的长度,占用存储空间且降低性能,另外,所有列总长度被限制为65,535字节。

  2. text、blob字段应该从频繁查询的表中分离出去,因为text、blob之类的长列会完全被MySQL保存在一个单独的数据页里面里,查询效率低。

  3. 不要轻易使用查询缓存,特别是写密集型应用,缓存失效会占用大量的系统资源。

二、Oracle 中的 in 参数的个数限制

Oracle 中 in 后括号中的参数个数有限制,Oracle 9i 中个数不能超过256,Oracle 10g个数不能超过1000。
当in的个数大于1000时,有以下两个解决办法:

  1. 对参数进行处理,分成多个in,其中每个in列表中参数都小于1000。如 params in(1,2,3…1000) or params in(1001,1002…2000)。
    不过这种方法性能和维护性方面不好
  2. 将in后面的字符串改成子查询,将in里面的数据保存到临时表中,params in(select …from dual)

三、过滤条件 where 和 having 的区别

  1. where 是一个约束声明,使用 where 约束来自数据库的数据,where 是在结果返回之前起作用,where 中不能使用聚合函数。
  2. Having 是一个过滤声明,是在查询返回结果集以后对查询结果进行的过滤操作,在 Having 中可以使用聚合函数。
  3. 在查询过程中,where 子句执行优先级高于聚合语句。聚合语句(sum,min,max,avg,count)优先级高于 having 子句。

四、一个表建有多个索引,Oracle 如何选择

一个表最多可有255 个字段和32个索引。

  1. 表的主键、外键必须有索引;
  2. 数据量超过300的表应该有索引;
  3. 经常与其他表进行连接的表,在连接字段上应该建立索引;
  4. 经常出现在Where子句中的字段,特别是大表的字段,应该建立索引;
  5. 索引应该建在选择性高的字段上;
  6. 索引应该建在小字段上,对于大的文本字段甚至超长字段,不要建索引;
  7. 复合索引的建立需要进行仔细分析;尽量考虑用单字段索引代替:
    ①正确选择复合索引中的主列字段,一般是选择性较好的字段。
    ②复合索引的几个字段是否经常同时以 AND 方式出现在 Where 子句中?单字段查询是否极少甚至没有?如果是,则可以建立复合索引;否则考虑单字段索引。
    ③复合索引中包含的字段经常单独出现在 where 子句中,则分解为多个单字段索引。
    ④复合索引所包含的字段超过3个,要仔细考虑必要性,考虑减少复合的字段。
    ⑤既有单字段索引,又有这几个字段上的复合索引,可以删除复合索引。
  8. 频繁进行数据操作的表,不要建立太多的索引;
  9. 删除无用的索引,避免对执行计划造成负面影响;
    以上是一些普遍的建立索引时的判断依据。一言以蔽之,索引的建立必须慎重,对每个索引的必要性都应该经过仔细分析,要有建立的依据。因为太多的索引与不充分、不正确的索引对性能都毫无益处:在表上建立的每个索引都会增加存储开销,索引对于插入、删除、更新操作也会增加处理上的开销。另外,过多的复合索引,在有单字段索引的情况下,一般都是没有存在价值的;相反,还会降低数据增加删除时的性能,特别是对频繁更新的表来说,负面影响更大。

五、商品表,商品有类目属性,找出某个类目下最新创建的100个商品,表索引如何设计

  1. 类目加索引,需要遍历类目下所有商品,当类目商品数量多时,执行速度慢,不同类目的执行效率不一样。
  2. 创建时间加索引,执行过程会命中创建时间索引,按照时间倒排筛选类目,如果当前类目很长时间没有新品创建,有可能遍历整个表。
  3. 类目+创建时间联合索引,先命中类目索引,然后按照创建时间后续遍历就可以拿到最新的100条。

六、一个6亿的表A,一个3亿的表B,通过外键tid关联,如何最快查询出有关联关系的第50000到第50200中的这200条数据记录

1、如果 A 表 TID 是自增长,并且是连续的,B 表的 ID 为索引
select * from a,b where a.tid = b.id and a.tid>500000 limit 200;
2、如果 A 表的 TID 不是连续的,那么就需要使用覆盖索引。TID 要么是主键,要么是覆盖索引,B 表 ID 也需要有索引。
select * from b, (select tid from a limit 50000,200) a where b.id = a.tid;

总结:SQL调优方法很多,同样的查询结果可以有很多种不同的查询方式。其实最好的方法就是在开发环境中用最贴近真实的数据集和硬件环境进行测试,然后再发布到生产环境中。

国产Flash替代方案:手把手教你用XSCT烧写ZYNQ7045的BOOT.BIN(附完整命令解析) 本文详细介绍了国产Flash替代方案在ZYNQ7045上的应用,通过XSCT工具链实现BOOT.BIN的精准烧写。内容涵盖国产Flash兼容性检查、PetaLinux环境搭建、XSCT烧写全流程及故障排查,帮助开发者高效完成国产化替代,提升硬件开发效率。 阅读详情

相关推荐

CTF命令执行绕过实战:从空格过滤到无回显外带的7种核心姿势

命令执行漏洞是Web安全中的常见高危漏洞,其核心原理在于应用程序未对用户输入进行充分过滤,导致攻击者能够注入并执行系统命令。在真实环境中,安全防护措施(如WAF、输入过滤函数)普遍存在,因此漏洞利用的关键技术在于“绕过”这些过滤机制。理解过滤器的运作逻辑(如黑名单、白名单、转义、长度限制)是成功绕过的前提。通过系统学习**空格绕过**、**命令黑名单绕过**、**编码混淆**等基础技巧,并结合**无回显外带**、**反弹Shell**等高级利用链,安全研究人员能够有效应对复杂防护场景。本文以CTFshow

weixin_29315091的博客 368

聊聊sql优化的15个小技巧

前言 sql优化是一个大家都比较关注的热门话题,无论你在面试,还是工作中,都很有可能会遇到。 如果某天你负责的某个线上接口,出现了性能问题,需要做优化。那么你首先想到的很有可能是优化sql语句,因为它的改造成本相对于代码来说也要小得多。 那么,如何优化sql语句呢? ​ 我的个人技术博客:https://susan.net.cn​​​​​​​ ​ 这篇文章从15个方面,分享了sql优化的一些小技巧,希望对你有所帮助。 最近无意间获得一份BAT大厂大佬写的刷题笔记,一下子打通了我的任督二脉,越来越觉得算法没

9683

Java 简易版 UDP 多人聊天室

【代码】Java 简易版 UDP 多人聊天室。

nmy15570188135的博客 1187

SQL语句的优化

SQL优化

lpf11214的博客 3533

单细胞分析进阶:sctransform标准化在Seurat中的实战解析

本文深入解析了sctransform标准化方法在Seurat单细胞分析中的实战应用。通过对比传统对数标准化,sctransform能更有效地建模并剔除技术噪音,提升数据质量。文章提供了从环境配置、数据准备、核心参数解析到完整流程整合的详细指南,并针对常见问题给出解决方案,帮助研究者获得更清晰的细胞分群和更可靠的差异表达结果。

weixin_29248313的博客 149

使用Typora时LaTeX内联公式简单汇总

0、前言 在使用Typora写笔记时,有时候需要添加上LaTeX排版的公式。以下是整理出的一份简单笔记,方便记忆不清楚时查阅。笔记暂时不够完善,之后再补充。 注:有些公式语法KateX不能解析,但在Typora中可以使用(不用在意) 1、一些基本内联公式 位置关系 展示 LaTeX 说明 x2x^{2}x2 x^{2} 右上标 x2x_{2}x2​ x_{2} 右下标 2x{}^{2}x2x {}^{2}x 左上标 2x{}_{2}x2​x {}_{2}x 左下标

白白旧维的博客 4438

20种sql语句优化方案

大家写sql语句中,是不是常有死锁、超时等问题出现,那就说明你的索引、查询语句规范并不完美。以下是小主整列20种sql语句优化方案,可以让你的sql语句,查询删除更加快速。当然看起来更加容易理解!

weixin_45836587的博客 4776

Grafana企业版vs开源版:从安装到插件管理的完整对比实测(含离线部署技巧)

本文深入对比Grafana企业版与开源版在安装流程、插件管理和功能限制等方面的差异,特别针对离线部署场景提供实用技巧。通过实测数据源支持、权限管理等核心功能,帮助企业用户做出明智选择,同时详细介绍离线安装和插件签名验证等关键操作。

weixin_29313817的博客 101

SQL优化的15个小技巧,纯干货分享!

普通索引最基本的索引,没有任何限制唯一索引与普通索引类似,不同的就是:索引列的值必须唯一,但允许有空值主索引即主键索引,关键字PRIMARY复合索引为了更多的提高MySQL效率可建立组合索引,遵循“最左前缀”原则全文索引可用于MyISAM表,MySQL5.6之后也可用于innodb表,用于在一篇文章中,检索文本信息的, 针对较大的数据,生成全文索引很耗时和空间以上就是目前我对SQL优化的一些个人理解和总结,如果遗漏,欢迎评论区补充说明!

黄团团的个人博客 2万+

1、JMP脚本编程全面指南:从基础到高级应用

本博客全面介绍了JMP脚本编程的各个方面,从JMP基础和JSL入门,到数据类型、数据结构、编程方法、数据表操作、图形与三维场景脚本,再到应用程序创建与扩展功能。内容涵盖脚本工具使用、常见任务实现、兼容性说明及未来发展趋势,旨在帮助用户掌握JMP脚本语言的强大功能,提升数据分析的自动化与定制化能力。适合从初学者到高级用户的深入学习与实践参考。

flink9streamer的博客 266

【硬刚Hadoop】HADOOP MAPREDUCE(1):概述

本文是对《【硬刚大数据之学习路线篇】从零到大数据专家的学习指南(全面升级版)》的Hadoop部分补充。 1 MapReduce定义 MapReduce是一个分布式运算程序的编程框架,是用户开发“基于Hadoop的数据分析应用”的核心框架。 MapReduce核心功能是将用户编写的业务逻辑代码和自带默认组件整合成一个完整的分布式运算程序,并发运行在一个Hadoop集群上。 2MapReduce优缺点 2.1 优点 1)MapReduce易于编程 它简单的实现一些接口,就可以完成一个分布式程序..

微信搜:import_bigdata,大数据领域硬核原创作者 461

关于SQL优化的二十个小方法

关于SQL优化的二十个小方法

weixin_72984629的博客 2571

5G射频到底是啥?方案怎么搭?工作流程、SAW选型、PA选型一口气讲透(工程师秒懂版)

很多人一提 5G 射频,脑子里先冒出来的是几个零件名:👉 PA👉 LNA👉 SAW👉 天线👉 开关但真正做方案时,这些东西不是一堆分立器件,而是一条完整的“信号流水线”。更准确地说,。Qualcomm 对 RFFE 的定义就是“把信息转换成可发送的射频信号,并把接收到的信号转换回有用信息”的那一整套组件。

weixin_43199439的博客 532

[MySQL]SQL优化之sql语句优化

SQL查询优化在MySQL数据库中是提高性能的关键步骤之一。本文总结了一系列针对SQL查询的优化技巧,以帮助开发者改善查询性能,降低系统负载。

Panci_的博客 1490

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

Sql(sql语句优化,索引设计优化)

Sql(sql语句优化,索引设计优化)

轻言细语莫泪痕 1952

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

SQL语句的优化技巧

通过合理创建索引、使用查询分析器分析执行计划以及重构SQL语句,可以显著提高查询性能。在实际项目中,优化SQL语句是一个持续的过程,需要根据具体的业务场景和数据量进行调整。

qq_38566870的博客 889

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

SQL语句的自动优化

在数据库应用系统中编写可执行的SQL语句可以有多种方式实现,但哪一条是最佳方案却难以确定。为了解决这一问题,有必要对SQL实施优化。简单地说,SQL语句的优化就是将性能低下的SQL语句转换成达到同样目的的性能更好的SQL语句。 优化SQL语句的原因 数据库系统的生命周期可以分成: 设计、开发和成品三个阶段。在设计阶段进行优化的成本最低,收益最大。在成品阶段进行优化的成本最高,收益最小。如果将一个数

云中客的专栏 2790

sql in语句优化_干货:30种SQL语句优化!

 - 点击上方“中国统计网”订阅我吧!-在sql查询中为了提高查询效率,我们常常会采取一些措施对查询语句进行sql优化,下面总结一些方法,供大家参考。01对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。02应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描。03应尽量避免在 whe...

weixin_39531582的博客 1216

如何对 SQL 语句进行优化

当我们在设计一个项目时,开发阶段的业务数据量相对较少,一些 SQL 语句的执行效率对程序运行效率的影响不太明显,所以对于开发或运维人员来说不会注重对 SQL 语句的优化。但是,随着时间的积累,业务数据量会越来越多,SQL 的执行效率对程序的运行效率的影响逐渐增大,此时对SQL的优化就很有必要。 本篇章主要从以下几个方面对 SQL 语句的优化进行介绍: 插入数据优化 主键优化 order by 优化 group by 优化 limit 优化 count 优化 update 优化

S mile0804的博客 4151

sql语句优化

sql语句优化 性能不理想的系统中除了一部分是因为应用程序的负载确实超过了服务器的实际处理能力外,更多的是因为系统存在大量的SQL语句需要优化。为了获得稳定的执行性能,SQL语句越简单越好。对复杂的SQL语句,要设法对之进行简化。常见的简化规则如下: 1)不要有超过5个以上的表连接(JOIN)2)考虑使用临时表或表变量存放中间结果。3)少用子查询4)视图嵌套不要过深,一般视图嵌套不要超过2个为宜。

曹胜欢 1万+

SQL语句优化

一、找出导致性能慢的原因       首先你要知道是否跟sql语句有关,然后使用sql性能检测工具--sql server profiler,分析出sql慢的相关语句,就是执行时间过长,占用系统资源,cpu过多的 1.查看执行时间和cpu占用时间(查询后在消息中查看) set statistics time on select * from dbo.Product set stat...

爱笑的喵 7795

Oracle SQL语句优化【4】之使用SQL优化工具

SQL语句是对数据库进行操作的惟一途径,对数据库系统的性能起着决定性的作用。对于同一条件下的SQL语句写法有很多,其中一些写法往往对性能又有很大影响。但是每个人掌握SQL语言的水平不同,如何才能保证写出高性能的SQL呢?    针对这种情况,人工智能自动SQL优化工具应运而生。现在我就向大家介绍这样一款工具:SQL Tuning for SQL Server。 1. SQL Tuning

莫者兼爱任的专栏 5172

SQL优化SQL语句优化的目的

sql的优化,要看优化什么,性能,效率,稳定性,安全性?每个方面都有很大的不同。 内容参见:[https://blog.youkuaiyun.com/sinat_37464123/article/details/80954869](https://blog.youkuaiyun.com/sinat_37464123/article/details/80954869)。 一是格式优化,使sql看起来整洁,易读,这样对...

qq_43725031的博客 1353
上一篇: Oracle:decode 函数
下一篇: SQL 语句中的 1
JFS_Study
博客等级 码龄6年 363粉丝 359原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JFS_Study

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值