请教一个 sql 优化问题

2023-06-27 10:13:04 +08:00
 EggplantLover
摘了一段导致执行慢的条件,这种应该怎么优化

task.assignee_id_ = '123'
AND
(
(
task.STATUS_ = 'LOCK'
and
(
linkd.IDENTITY_ = '123'
or linkd.TYPE_ != 'user'
)
)
or
task.STATUS_ != 'LOCK'
)

列 task.assignee_id_、linkd.IDENTITY_已经加了索引
2111 次点击
所在节点    程序员
19 条回复
EggplantLover
2023-06-27 10:14:25 +08:00
去掉这段条件执行时间可以减少两秒,查询的表数据量都不大,几万行左右
Stevenv
2023-06-27 10:24:17 +08:00
你先 explain 执行 SQL, 看看索引的使用情况
Alias4ck
2023-06-27 10:36:10 +08:00
什么数据库,几万行的查询, 为啥可以这么慢😧
MartinDai
2023-06-27 10:40:33 +08:00
task.assignee_id 和 linkd.IDENTITY 看起来都是数字类型的 不要使用字符串做查询,改成数字
Hieast
2023-06-27 10:41:31 +08:00
linkd 和 task 不是一张表吧,多了 join ?
MartinDai
2023-06-27 10:41:42 +08:00
还有就是如果数据量这么小,完全可以在内存里做过滤
AND((task.STATUS_ = 'LOCK' and (linkd.IDENTITY_ = '123' or linkd.TYPE_ != 'user')) or task.STATUS_ != 'LOCK')
这后面的条件都可以去掉
wanniwa
2023-06-27 10:44:14 +08:00
把 or 拆成两个 sql 在数据里里试试两个哪个执行的慢,如果都快的话,看要不要就拆成两句直接 union 。如果分析出来哪个单句慢的话再针对单句继续优化
第一句
task.assignee_id_ = '123'
AND
(
task.STATUS_ = 'LOCK'
and
(
linkd.IDENTITY_ = '123'
or linkd.TYPE_ != 'user'
)
第二句
task.assignee_id_ = '123'
AND task.STATUS_ != 'LOCK'
DissDoge
2023-06-27 10:45:55 +08:00
可以考虑以下几点:

使用合适的索引:确保 task.assignee_id_和 linkd.IDENTITY_的索引是正确创建的。你提到已经添加了索引,但需要确保索引的创建方式正确,并且统计信息是最新的。可以使用数据库的索引优化工具或者执行计划分析来确认索引是否被有效使用。

优化逻辑表达式:该条件涉及多个逻辑运算符( AND 、OR ),可以尝试重新组织条件表达式,优化逻辑判断的顺序。例如,可以将常见的判断条件放在前面,以便更早地过滤掉不符合条件的记录。

考虑联合索引:如果 task.assignee_id_和 task.STATUS_、linkd.IDENTITY_和 linkd.TYPE_之间有相关性,可以考虑创建联合索引。联合索引可以更好地支持多个列的组合条件查询,提高查询效率。

数据库性能调优:除了索引优化外,还可以考虑其他数据库性能调优技术。例如,分析和优化查询计划、调整数据库配置参数、增加硬件资源等。

数据库版本升级:如果你使用的是较旧版本的数据库,可以考虑升级到最新版本,以获得更好的性能优化和查询优化器。

需要注意的是,优化查询的方法因数据库类型和版本而异。建议在具体情况下,结合数据库性能监控和优化工具,以及参考相关数据库的优化文档,针对具体的数据库系统进行优化调整。
8355
2023-06-27 10:47:50 +08:00
简单做法 拆分 sql
你这样分行真的看着有点心态爆炸
原代码
task.assignee_id_ = '123'
AND
(
(task.STATUS_ = 'LOCK' and (linkd.IDENTITY_ = '123' or linkd.TYPE_ != 'user'))
or task.STATUS_ != 'LOCK'
)

改进后
task.assignee_id_ = '123' and task.STATUS_ != 'LOCK'
task.assignee_id_ = '123' and task.STATUS_ = 'LOCK' and linkd.IDENTITY_ = '123'
task.assignee_id_ = '123' and task.STATUS_ = 'LOCK' and linkd.TYPE_ != 'user'
3 组数据按照你原本排序需求代码写下排序就行

如果 task.assignee_id_ = '123'查的结果并不多实际应该通过遍历过滤更快
数据库基本原则简单查询多次比复杂查询一次要快
ooee2016
2023-06-27 10:53:30 +08:00
新加个字段表示这段逻辑的状态
eightyfive
2023-06-27 11:11:09 +08:00
拆分 sql ,explain 一下,看看是否有索引,以及确认 sql 字段走索引的前后顺序
kkwa56188
2023-06-27 11:14:36 +08:00
试试把 linkd 相关的条件, 改用 exists 重写子句, 这样 就不用在 主 查询 里 join 一次
0x1111
2023-06-27 13:11:50 +08:00
show create table
explain
select count(distinct(assignee_id_))

没有表结构和 explain 不好具体分析,字段加索引不一定最有,还要看下列的分散度
EggplantLover
2023-06-27 14:51:10 +08:00
@8355 #9 这样改了时间上没有变化,可能解析器最终都会改成一样的
akira
2023-06-27 14:52:44 +08:00
就 2 个几万行的表 jion 的话,应该是随便 zuo 的,数据库配置那边也看一眼呢。
EggplantLover
2023-06-27 15:00:02 +08:00
@akira #15 一共十个表 join ,我把比较慢的条件摘了出来
8355
2023-06-27 15:13:56 +08:00
@EggplantLover #14 没有变化就是你索引的问题了,or 是不走索引的, 如果你原本就没有索引的话。。。。。。。。。
tairan2006
2023-06-27 15:18:12 +08:00
10 个表 join…与其优化 sql 不如搞个物化视图或者做个宽表……
EggplantLover
2023-06-27 16:17:39 +08:00
@Alias4ck #3 达梦

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/951969

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX