sql - 如何根据多列有效地选择 NON-NULL、NON-EMPTY 行?
问题描述
下面的查询有效,但是我想知道是否有办法优化它?就目前而言,它将为每个 OR 语句执行多个表扫描?
我在查询中采取防御措施的原因是,如果有人在 #{phone} 或 #{email} 中传递 NULL 或空字符串,它将进一步删除流程中的大量数据。因此,必须只为每个 OR 语句选择强匹配值。
SELECT ID
FROM...
WHERE (phone != '' AND phone IS NOT NULL AND phone = #{phone})
OR (phone2 != '' AND phone2 IS NOT NULL AND phone2 = #{phone})
OR (phone3 != '' AND phone3 IS NOT NULL AND phone3 = #{phone})
OR (email != '' AND email IS NOT NULL AND email = #{email})
解决方案
我认为phone
应该在应用层而不是数据库中对参数进行清理。
但是,如果它像您提到的那样至关重要,有时可以方便地采取一些安全措施,例如您正在使用的那些。如果是这种情况,则查询看起来不错。
从性能的角度来看,查询可以从索引中受益:
create index ix1 on t (phone);
create index ix2 on t (phone2);
create index ix3 on t (phone3);
create index ix4 on t (email);
现在,根据优化和数据直方图,引擎可能会选择避免索引。UNION
如果是这种情况,您可以通过使用而不是OR
(旧技巧)改写查询来促进上述索引的使用。例如:
SELECT ID
WHERE (phone != '' AND phone IS NOT NULL AND phone = #{phone})
FROM...
UNION
SELECT ID
WHERE (phone2 != '' AND phone2 IS NOT NULL AND phone2 = #{phone})
FROM...
UNION
SELECT ID
WHERE (phone3 != '' AND phone3 IS NOT NULL AND phone3 = #{phone})
FROM...
UNION
SELECT ID
WHERE (email != '' AND email IS NOT NULL AND email = #{email})
OR
当谓词中没有 s 时,引擎使用索引要容易得多。然而,这个技巧在稍后执行UNION
s 时会付出代价。如果所选行数很少,则此成本应该是微不足道的。
推荐阅读
- javascript - 在 Firebase 中添加便利功能
- javascript - 用两个日期之间的日期填充对象数组
- azure - 使用 terraform 在 azure kubernates 中启用虚拟节点
- biml - 尝试在 BIML 中设置数据流 AutoAdjustBufferSize 时出错
- java - 每个单元格等于一个对象而不是行的表格
- redis - 什么是在 CLIENT LIST 中生成 redis cmd=info?
- web-services - Acumatica 从 V6 升级到 2018R2 后,基于“准备发票”屏幕的 Web API 停止工作
- postgresql - 如何在 Apache Ignite 中按需将 Posgres 表缓存为第 3 方持久性?
- python - Python子进程输出格式?
- pdo - PDO:在 localhost ubuntu 18.04 上找不到驱动程序