database - 使用多个连接和可选参数进行查询

标签 database oracle performance

我有一个搜索应用程序。有 7 个字段(名字、姓氏、电话、街道、城市、商店号码、信用卡号码),用户可以在其中写入参数,它会在数据库中找到他的客户。一切都在 AND 条件下工作,所以当名字是“Andy”而姓氏是“Larkin”时,只会找到 Andy Larkins 等。用户可以将字段留空,这意味着当名字是“Andy”时,它应该会找到所有 Andys 等。数据库如下所示:

enter image description here

“关系”表用于连接人和商店。一个人必须有 1 个地址、1 个商店,可以有多个地址、多个商店并且没有信用卡/多张信用卡。现在,我必须在一个查询中处理所有的过滤,我不能先检查一些条件然后用另一种方式构造查询,我只是没有那个选项。

当我按名字或姓氏搜索时,速度很快(均在 Person 表中),但当我按电话号码或信用卡号码搜索时,会花费很多时间。数据库中有很多数据,但我的查询仍然很糟糕,我不太擅长编写查询,尤其是在 Oracle 中。这是查询:

SELECT
    PERSON.personId,
    PERSON.firstName,
    PERSON.lastName
    ADDRESS.street,
    ADDRESS.city,
    ADDRESS.phoneNumber
FROM
    PERSON
    LEFT JOIN ADDRESS ON PERSON.personId = ADDRESS.personId,
    LEFT JOIN RELATION ON PERSON.personId = RELATION.personId,
    LEFT JOIN SHOPS ON RELATION.shopId = SHOPS.shopId
    LEFT JOIN CREDITCARDS ON PERSON.personId = CREDITCARDS.personId
WHERE
    PERSON.firstName = NVL(?, PERSON.firstName),
    PERSON.lastName = NVL(?, PERSON.lastName),
    ADDRESS.phoneNumber = NVL(?, ADDRESS.phoneNumber),
    ADDRESS.street = NVL(?, ADDRESS.street),
    ADDRESS.city = NVL(?, ADDRESS.city),
    SHOPS.shopNumber = NVL(?, SHOPS.shopNumber),
    CREDITCARDS.creditCardNumber = NVL(?, CREDITCARDS.creditCardNumber);

用户留空的参数作为 NULLS 传递,这就是我使用 NVL 的原因。当我删除所有条件并留下信用卡号时,它会很快,所以我想这意味着所有不必要的条件检查都会减慢查询速度,而且在大多数情况下我真的不需要那个条件检查,它只是以防用户传递某些东西。

如果我可以选择检查条件然后才构建查询,那么我将只添加所需的条件,但我没有该选项。我正在考虑在查询中添加一些“IF”,但我不确定这是否可能,我能找到的只是“IF/CASE WHEN”,但找不到适用于我的案例的任何示例。我也试过这个:

...WHERE (? IS NULL OR (PERSON.firstName = NVL(?, PERSON.firstName))) AND...

这没有帮助,我得到了大量重复的结果(仅在地址或其他方面有所不同 - 一个人可以有多个地址)结果(即使使用“DISTINCT”)。

这不是作业,那个数据库很大,还有很多其他字段,但是我在这里简化了它,那里也有很多数据。感谢您的帮助。

最佳答案

这里有几点需要考虑。

  1. 注意可能没有意义的查询;例如那些查询信用卡号和地址的。这种性质的查询会落入粉丝陷阱。
  2. 在数据库中创建引用完整性约束将允许优化器执行连接消除。
  3. 如果您可以动态构建查询“where 子句”而不是使用 NVL 函数,那么对于优化器来说会好得多。

关于database - 使用多个连接和可选参数进行查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41622441/

相关文章:

php - 显示变量从 1 .php 到另一个 .php 时出现问题

mysql - 鸡尾酒配方的数据库结构

oracle - 如何在Oracle 11g中创建用户并授予权限

javascript - 在 Scroll 上做点什么

database - IMDB(内存数据库)与 Java 集合

python - 检查 Google App Engine 数据存储区实体是否具有特定属性

sql - 如何使用 pl sql block 对表中的数据进行排序

java - 如何在 while 循环中执行查询并执行 Qry 结果集?

java - 搜索策略以有效地从服务或服务器加载数据?

python - localhost django dev server vs. mac os 上的 postgres 慢?