记录日期: 2025年6月26日
今天阅读的内容非常贴近我们DBA与开发团队的日常协作。它深刻地揭示了一个事实:数据库的性能与安全,很大程度上取决于应用程序端的代码质量。作为DBA,我们的工作远不止是在服务器端调优,更重要的是“深入前线”,与开发人员并肩作战,将最佳实践落地在每一行代码中。同时,面对时序数据这类新场景,我们也需要承担起技术布道者和架构师的角色。
第一部分:SQL编写的“艺术” - 那些年我们一起填过的“坑”
这部分内容通过几个具体的案例,强调了SQL编写的规范性是多么重要。这些都是我们在SQL Review中反复强调的要点。
• 关于MyBatis开发框架使用绑定变量的事件: • 事件回顾: 案例很可能描述了开发人员在MyBatis的XML映射文件中,混用了 ${}
和#{}
,特别是将用户输入用${}
拼接到了SQL中。• DBA的视角: 这是我们DBA眼中最危险、最不可容忍的两种行为的结合体: 1. 安全上: 使用 ${}
进行字符串替换,是SQL注入的直接源头。这是最高级别的安全漏洞,我们必须严防死守。2. 性能上: 每次传入不同的参数,都会生成一条全新的SQL文本。这会导致数据库(尤其是Oracle)的共享池(Shared Pool)被“打爆”,优化器无法重用执行计划,每次都需要进行成本高昂的 “硬解析” 。在高并发下,这会迅速耗尽CPU资源,导致系统瘫痪。 • 我们的最佳实践: 必须强制要求,所有与数据值相关的动态部分,一律使用 #{}
。这会生成带绑定变量(Bind Variables) 的预编译SQL(Prepared Statement),既能从根本上杜绝SQL注入,又能让数据库高效地重用执行计划。这是DBA与开发团队之间关于数据库安全和性能的“第一道约定”。• 使用 EXISTS
的SQL语句的改写:• DBA的视角: 我们通常认为,在子查询中, EXISTS
的性能优于IN
,因为它遵循“找到即停”的逻辑(半连接,Semi-Join),尤其是在子查询结果集很大时。但是,书中可能探讨了更精进的改写方式。例如,在某些场景下,将EXISTS
子查询改写成一个LEFT JOIN ... WHERE B.ID IS NOT NULL
或者INNER JOIN
,可能会让优化器有更多的选择空间(如调整JOIN
顺序、使用不同的JOIN
算法),从而生成更优的执行计划。• 我们的最佳实践: 不存在一成不变的“最优”写法。作为DBA,我们的职责是基于我们所用的特定数据库版本和数据分布,对不同的写法进行 EXPLAIN
分析和实际测试,然后将最适合当前场景的模式总结为团队的开发规范。• 设计上出发减少SQL的标量子查询: • DBA的视角: 标量子查询(Scalar Subquery),即出现在 SELECT
列表中的子查询(如SELECT a.col1, (SELECT b.col2 FROM B b WHERE b.id = a.id) FROM A a
),是性能的“隐形杀手”。它的执行模式,往往是外层查询每返回一行,子查询就要独立执行一次。如果外层查询返回一万行,子查询就要执行一万次!• 我们的最佳实践: 必须在设计和Code Review阶段就杜绝这种写法。最有效的改写方式就是将其转化为 LEFT JOIN
:SELECT a.col1, b.col2 FROM A a LEFT JOIN B b ON a.id = b.id
。这样,优化器就可以用一个整体的、高效的JOIN
操作来代替成千上万次的独立查询。教会开发人员识别并改写标量子查询,是DBA性能调优培训的重要一课。
第二部分:拥抱新场景 - 时序数据库的最佳实践
随着物联网(IoT)、系统监控等场景的兴起,时序数据库(Time-Series Database)越来越普及。作为DBA,我们不能固守在关系型数据库的一亩三分地,必须掌握这些新型数据库的使用和管理之道。
• 时序数据库的数据库表设计: • DBA的视角: 时序数据的表设计与传统关系型数据库截然不同。核心思想是 “Tall and Skinny” (高瘦表)模型,即一张表包含时间戳、度量名称、标签集(Tags)和度量值。 • 关键设计点: 1. 时间戳(Timestamp): 必须是主键或第一索引列。 2. 标签(Tags): 这是时序数据库的精髓。所有用于查询和过滤的元数据(如设备ID、机房、IP地址)都应该作为标签,并且必须被索引。 3. 度量(Metrics/Fields): 真正的度量值(如CPU使用率、温度)应该作为普通字段,通常不建议索引。 4. 分区(Partitioning): 必须基于时间进行分区。这是时序数据库能够高效管理海量数据的根本。我们可以轻松地删除( DROP
)过期的旧分区,这个操作远比DELETE
要快。查询时,也能通过时间范围进行有效的分区裁剪。• 时序数据库的数据分析: • DBA的视角: 我们需要引导开发人员放弃传统SQL的思维,拥抱时序数据库提供的专用分析函数。例如,进行时间维度的聚合,应该使用 time_bucket()
或date_trunc()
这类函数,而不是在原始时间戳上做GROUP BY
。获取某个时间窗口的第一个/最后一个值,应该使用first()
/last()
函数。这些专用函数都是针对时序数据结构进行过深度优化的。
总结:
今天的学习内容,深刻地体现了现代DBA角色的演进。我们一方面是 “代码质量教练”,需要深入到开发流程中,将SQL安全和性能的最佳实践传递给每一位开发者。另一方面,我们也是 “新技术领航员”,当新的业务场景(如时序数据)出现时,我们需要负责评估、引入并制定新数据库平台的使用规范和最佳实践。这种既能深入细节抓SQL,又能抬头看路引架构的“协同作战”能力,正是我们DBA的核心价值所在。
文章转载自青年数据库学习互助会,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




