在 SQL 中,动态过滤经常是必需的,比如在报告或搜索中,当过滤器由用户设置时。主要方法:
(@param IS NULL OR 字段 = @param) 的结构,以便在未设置参数时额外的条件不会影响结果。该方法安全,但有时会导致索引的非优化使用。订单搜索的模板示例:
SELECT * FROM Orders WHERE (@CustomerID IS NULL OR CustomerID = @CustomerID) AND (@Status IS NULL OR Status = @Status) AND (@DateFrom IS NULL OR OrderDate >= @DateFrom) AND (@DateTo IS NULL OR OrderDate <= @DateTo);
问题: 为什么在使用 (@param IS NULL OR Column = @param) 方法时,性能有时会下降——即使 Column 上有索引?
答案: 这种模板会阻碍优化器有效使用索引,因为条件中参与的是变量,查询将变为完整的表扫描,而不是索引查找。在大数据量时,这非常关键。
示例:
WHERE (@name IS NULL OR name = @name)
这个条件与简单的 name = @name 不同,导致数据库无法轻松使用索引。
历史
在客户数据库搜索服务中,通过模板 (@par IS NULL OR Field = @par) 引入了“灵活过滤器”,但在订单数量增长时,搜索速度从秒降至分钟——索引失效,因为优化器无法确定具体值。
历史
在电子商务项目中,过滤通过动态 SQL 收集,未使用参数,直接插入值。注入使用户能够获取所有客户列表,因为过滤器存在漏洞——不得不紧急更改密码。
历史
BI 报告通过参数化模板生成,而未考虑到 OR 条件会消除索引扫描。在百万级数据集上,报告“卡住”,直到将过滤重写为具有必要条件和不同参数组合的独立逻辑的优化版本。