那么挑战来了,这条 sql 还能有更优化性能的写法吗?

2016-06-15 17:04:10 +08:00
 teemoer

http://ww3.sinaimg.cn/large/e38a7f8bgw1f4w0tyljcuj20kt0k1juw.jpg

SELECT m.id, m.name, mc_diag.count_size AS mc_diag_count, mc_thers.count_size AS mc_thers_count, mc_me.count_size AS mc_me_count FROM medicine m LEFT JOIN medicine_count mc_diag ON mc_diag.medicine_id = m.id AND mc_diag.doctor_id = 47 AND mc_diag.diagosis_name = '急性上呼吸道感染' LEFT JOIN medicine_count mc_me ON mc_me.medicine_id = m.id AND mc_me.doctor_id = 47 LEFT JOIN medicine_count mc_thers ON mc_thers.medicine_id = m.id AND mc_thers.doctor_id <> 47 WHERE (m.name LIKE '%w%' OR m.help_code LIKE '%w%') AND m.type = 0 GROUP BY m.name ORDER BY mc_diag_count DESC, mc_me_count DESC, mc_thers_count DESC, m.id DESC LIMIT 0, 10;

########################################## 鄙人的智商也就这么多了,诸位 SQL 大神多多指教

6420 次点击
所在节点    MySQL
69 条回复
sampeng
2016-06-15 19:39:45 +08:00
还有你现在查询速度是多少。。。
sampeng
2016-06-15 19:42:08 +08:00
数据量小于 10w 级别。。执行时间就 20-30ms 。优化他干嘛?
反之,我倒觉得,如果能修改数据库结构,改表结构。降低复杂查询。(就是反范式拉~)。比优化 sql 要简单一点。。
icaca
2016-06-15 19:46:48 +08:00
跑个执行计划看下
icaca
2016-06-15 19:48:44 +08:00
恕我才疏学浅, group by name,为何还能 select id,name?
Infernalzero
2016-06-15 20:21:57 +08:00
@ixiaozhi
join 对数据库性能消耗巨大,一般不是搞那种访问量比较少的网站或者封闭系统的话都不推荐用
现在基本都是靠宽表冗余字段,用空间换时间的,数据库只做简单的存储功能
而且 join 对于后续数据库做水平分割是个大坑
lecher
2016-06-15 20:33:24 +08:00
反 SQL 范式是为了便于读几十倍于写入的业务模式下,分布式部署的多机性能。在互联网领域,一台 db 要承担很多台应用服务器的数据查询负载。

所以尽量一次一个单表查询,便于控制索引和利用缓存。
为了减少联表查询,还会做冗余字段。保证单表数据可以满足查询结果。
应用服务器还会根据请求打包缓存,尽量做到一个请求过来直接在缓存上取完所有数据,避免查询打到数据库上。

做报表是另一种业务模式,查询比写入少,大部分 SQL 语句一周也跑不了几次,如果在互联网公司,喜欢取数据出来,在程序里面算,但是交付给 IT 技能很弱的单位那种项目,没人维护代码,大部分查询计算都交给数据库处理,反正一周也没有几次,直接一条 sql 语句跑完计算,算一次十几秒也无所谓,反正同一条语句一天也跑不了几次。这种项目做 sql 优化,把让代码处理数据,也不会有人维护,下一次有新业务来,看数据库表结构去拼 sql 的工作量肯定要比看代码去调用接口的工作量低,看别人写的代码和文档多累,直接看数据库表结构, sql 写出来跑就是了 。别想太多优化的事情,非要优化,开汇总表,半夜啥的做任务队列慢慢跑,看汇总就好了,报表有延时看不到实时数据也是可以接受的。
CinderellaCiCi
2016-06-15 20:48:15 +08:00
路过…
好多 left join 同一个表,还有两个 like ,(⊙o⊙)…
还有你没有提供各表数据量信息和索引信息,可能也是大家给不了你切实建议的原因之一。
neoblackcap
2016-06-15 20:54:28 +08:00
@icaca MySQL 乱合并,反正我没见 PostgreSQL 能这样写还不报错
coolcfan
2016-06-15 21:00:15 +08:00
曾经在压力测试里见过 SQL 改动导致数据库服务器 CPU 被占满……而且 sy 特别高
msg7086
2016-06-15 22:05:54 +08:00
有些逻辑最好在程序里完成,而不是在数据库上。
teemoer
2016-06-15 23:22:13 +08:00
@sampeng 谢谢 学习了哈 现在我电脑上面查是 27MS 服务器上面是 1S588MS
teemoer
2016-06-15 23:26:29 +08:00
@lecher 0.0 感谢大叔你回复的 514 个字(加上标点和回车等...) 学习了 ありがとうございます.
teemoer
2016-06-15 23:27:10 +08:00
@CinderellaCiCi 明白 谢谢 我打算听大家的 把一部分逻辑判断丢给程序来做
cevincheung
2016-06-15 23:27:51 +08:00
只有我觉得这种 SQL 该上第三方工具了么?
ichou
2016-06-15 23:59:42 +08:00
除了楼上各位讨论的把逻辑放到 业务代码中去 以及 反范式问题

联表联到这么复杂,我会去探究是不是表设计本身就不够健壮
如果这个查询的频率很高,直接导致系统性能瓶颈的话,可以试着建一个用来优化查询的冗余表。冗余表可以根据实时性要求的不同用定时脚本来更新

如果只是一天跑几次,还是自己人用, 1s 、 2s 的, who care ?
teemoer
2016-06-16 01:32:02 +08:00
@ichou = = 需求变动才 需要这样去做的. 我也是半路接手项目,之前 做这个的大神没考虑到后续的这些复杂需求, 我打算该表或者分表或者放到业务代码里面去.....

这条代码经常都会用到 非常频繁的
halden
2016-06-16 06:22:52 +08:00
其实我没看明白为什么 left join mc_me 之后还要 left join mc_others 。。第一个 join 的时候不是把 doctor_id = 47 拿了过来,然后呐? anyway 我是不明白 mc_me 和 mc_others 这两个表的意义何在。。
will0404
2016-06-16 08:44:54 +08:00
@fireapp 能解释下为什么吗? 确定会得到 1 abc o2 这样的数据?
DRcoding
2016-06-16 09:04:10 +08:00
看到医药业的 sql 甚是亲切啊,之前写了无数统计医院业务逻辑的存储过程....

少年,你不先看下数据库的执行计划再谈优化嘛。
dexterz
2016-06-16 11:24:48 +08:00
join on 后面的 and 移到 where 语句里面

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

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

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

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

© 2021 V2EX