【问题标题】:Optimize sql query with multiple joins on single table使用单个表上的多个连接优化 sql 查询
【发布时间】:2017-08-22 12:43:12
【问题描述】:

tbl_picklist 表

id     value
1      John
2      Mumbai
3      San Diego
4      CA
5      Jerry

tbl_user 表

id     picklist_id_name    email
1      1                   john@test.com
2      8                   jerry@gmail.com

tbl_profile 表

id     user_id   picklist_id_addr    picklist_id_addr2   designation
1       1         3                   5                   Dev
3       2         7                   3                   QA   

Picklist 是一个表格,您将在其中获取地址、地址 2 和名称的值, 我写的查询给了我想要的结果

SELECT
    u.email,
    p1.value AS username,
    p2.value AS addr1,
    p3.value AS addr2
FROM tbl_user u
LEFT JOIN tbl_picklist AS p1
    ON u.picklist_id_name = p1.id
LEFT JOIN tbl_profile pr
    ON pr.user_id = u.id
LEFT JOIN tbl_picklist AS p2
    ON p2.id = pr.picklist_id_addr
LEFT JOIN tbl_picklist AS p3
    ON p3.id = pr.picklist_id_addr2

结果:

email            username      addr1        addr2
john@test.com    John          Mumbai       San Diego
jerry@gmail.com  Jerry         CA           Mumbai

要获得上述结果,我需要在选择列表表上编写 3 个连接, 有没有其他方法可以让我只通过选择列表表上的一个连接来获得结果? 我在应用程序中有这种表结构,许多值存储在选择列表表中,执行这种查询需要很多时间。

【问题讨论】:

  • 问题不在于连接,而在于您没有调整查询。您是否应用了任何索引?
  • @TimBiegeleisen 是的,所有表都有索引
  • 哪些列有索引?
  • 在选项列表中,值列
  • 请使用explain analyze 的输出更新您的帖子,并提供应用于这些表的确切索引定义。

标签: sql postgresql join left-join


【解决方案1】:

当前的数据库结构不正确。 如果您有权利,您应该重建它以优化您的查询并遵循规范化形式。 例如,picklist_id_addr、picklist_id_addr2 和它们的值应该在一个表中,您可以在 picklist_id_name 或 user_id 上加入。

【讨论】:

    【解决方案2】:

    我打算建议为您的表添加一系列索引以希望加快查询速度,直到我意识到更大的问题是您当前的表设计。最大的罪魁祸首是下表tbl_picklist

    id     value
    1      John
    2      Mumbai
    3      San Diego
    4      CA
    5      Jerry
    

    您将有关用户的各种信息存储在单个非规范化列中。相反,我建议只使用两张表,一张用于用户信息,另一张用于地址信息。通过主外键关系将用户链接到地址。例如:

    tbl_user
    id | email           | designation | address_id
    1  | john@test.com   | dev         | 1
    2  | jerry@gmail.com | QA          | 2
    

    tbl_address
    id | city      | state     | country
    1  | San Diego | CA        | USA
    2  | Mumbai    | Bollywood | India
    

    在这个简化的架构下,您只需要一个查询来构建整个用户记录:

    SELECT
        t1.email,
        t1.designation,
        t2.city,
        t2.state,
        t2.country
    FROM tbl_user t1
    INNER JOIN tbl_address t2
        ON t1.address_id = t2.id
    

    例如,如果您仍然需要优化上述查询或类似的查询,您只需要担心单个连接,而不需要 WHERE 子句。在这个人为的示例中,tbl_user.address_id 上的索引应该可以解决问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-10-16
      • 2023-03-12
      • 1970-01-01
      • 2012-06-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多