如何避免重复编写相同SQL查询语句,同时提升查询性能?
解决方案
1. 封装为视图(全局复用首选)
把固定的查询逻辑封装为数据库视图,一次创建所有场景都可以调用,完全消除重复代码:
-- 创建视图 CREATE VIEW vw_customer_base AS SELECT c.first_name, c.middle_name, c.last_name, c.birth_day, c.birth_month, c.birth_year, c.marital_status, c.education_status, c.departmant, c.create_date, c.create_user, c.modify_date, c.modify_user, c.place -- 过滤所需字段要一并加入 FROM customer c
调用时直接追加自定义WHERE条件即可:
-- 调用示例 SELECT * FROM vw_customer_base WHERE place='london' AND create_date>GETDATE()-100
性能说明:普通视图不会产生额外查询开销,数据库优化器会自动将你追加的过滤条件下推到customer基础表的查询逻辑中,执行计划和你手写完整SQL完全一致。
2. 单脚本复用用CTE(公用表表达式)
如果只是同一个SQL脚本内多次复用该查询逻辑,不需要全局共享,用CTE更灵活不需要额外创建数据库对象:
WITH customer_base AS ( SELECT c.first_name, c.middle_name, c.last_name, c.birth_day, c.birth_month, c.birth_year, c.marital_status, c.education_status, c.departmant, c.create_date, c.create_user, c.modify_date, c.modify_user, c.place FROM customer c ) -- 第一次查询 SELECT * FROM customer_base WHERE place='london' AND create_date>GETDATE()-100; -- 同脚本内第二次查询 SELECT * FROM customer_base WHERE marital_status='married' AND departmant='HR';
3. 参数化复用选内联表值函数
如果常用过滤逻辑可以参数化,选择内联表值函数,兼顾复用性和性能:
-- 创建内联表值函数 CREATE FUNCTION fn_query_customer ( @place NVARCHAR(100) = NULL, @min_create_date DATE = NULL ) RETURNS TABLE AS RETURN ( SELECT c.first_name, c.middle_name, c.last_name, c.birth_day, c.birth_month, c.birth_year, c.marital_status, c.education_status, c.departmant, c.create_date, c.create_user, c.modify_date, c.modify_user FROM customer c WHERE (@place IS NULL OR c.place = @place) AND (@min_create_date IS NULL OR c.create_date > @min_create_date) )
调用时直接传入参数即可:
SELECT * FROM fn_query_customer('london', DATEADD(DAY,-100,GETDATE()))
性能说明:内联表值函数支持过滤条件下推,性能和原生SQL一致,不要使用多语句表值函数,会产生额外性能损耗。
额外性能优化建议
- 给常用过滤字段(比如place、create_date、departmant、marital_status)创建非聚集索引,无论用上面哪种封装方式都能大幅提升查询速度
- 如果customer表读多写少、查询对实时性要求不高,可以使用物化视图(实体化视图)预存查询结果,进一步降低查询耗时,写入场景会有额外开销需按需选择。
内容的提问来源于stack exchange,提问作者Kara
相关产品推荐
相关产品推荐

