0

我需要将两个具有相同列的表组合起来,并在复杂的 JOIN 查询中使用结果,但这会大大降低性能。这个带有 UNION 的查询的执行时间为 7 秒:

SELECT DISTINCT `admin`.`Fund_ID`,
                `admin`.`Fund_Name`
FROM (
        (SELECT *
         FROM `admin`)
      UNION
        (SELECT *
         FROM `admin_custom`
         WHERE `user_id`=361)) admin
LEFT JOIN (
             (SELECT *
              FROM `quant1`)
           UNION
             (SELECT *
              FROM `quant1_cust`
              WHERE `user_id`=361)) quant1 
ON (quant1.`Fund ID`=`admin`.`Fund_ID`)
WHERE quant1.`VaR 95`>-0.028

但是用一个简单的表替换 UNION 子句只需要 0.006 秒。如何解决性能问题?

4

2 回答 2

0

这涉及一些猜测 - 是否admin仅与quant1? 而admin_custom只是quant1_cust?那么这应该减少这两个字段的不同列表所需的工作量:

SELECT `Fund_ID`, `Fund_Name`
FROM `admin`
INNER JOIN `quant1` ON `admin`.`Fund_ID` = `quant1`.`Fund_ID`
                   AND `quant1`.`VaR 95`>-0.028

UNION

SELECT `Fund_ID`, `Fund_Name`
FROM `admin_custom`
INNER JOIN `quant1_cust` ON `admin_custom`.`Fund_ID` = `quant1_cust`.`Fund_ID`
                        AND `admin_custom`.`user_id` = `quant1_cust`.`user_id`
                        AND `quant1_cust`.`VaR 95`>-0.028
WHERE `admin_custom`.`user_id`=361
;

查看您现有的查询结构,我建议您不要做几件事。使用 UNION 和 SELECT DISTINCT 没有意义。不要将 select * 与 UNION 或 UNION ALL 一起使用 - 要具体且仅涉及您真正需要的字段。并且您现有的 where 子句确实会抑制左连接返回的任何空值 - 所以不要使用左连接。

SELECT DISTINCT --<< effort for distinctiveness here
...
FROM (
      SELECT * --<< too many fields
      ...
      UNION --<< effort for distinctiveness here

      SELECT * --<< too many fields
      ...
     )
LEFT JOIN (
            SELECT * --<< too many fields
            ...
            UNION --<< effort for distinctiveness here

            SELECT * --<< too many fields
            ...
           ) quant1
WHERE quant1 ...

编辑:替代 - 抱歉,这样可能更容易遵循:

SELECT `Fund_ID`, `Fund_Name`
FROM `admin`
INNER JOIN `quant1` ON `admin`.`Fund_ID` = `quant1`.`Fund_ID`
WHERE `quant1`.`VaR 95`>-0.028

UNION

SELECT `Fund_ID`, `Fund_Name`
FROM `admin_custom`
INNER JOIN `quant1_cust` ON `admin_custom`.`Fund_ID` = `quant1_cust`.`Fund_ID`
                        AND `admin_custom`.`user_id` = `quant1_cust`.`user_id`
WHERE `admin_custom`.`user_id`=361
AND `quant1_cust`.`VaR 95`>-0.028
;
于 2013-10-09T07:57:14.327 回答
0

您可以对数据库进行“附加更改”,以在 UNIONED 表之间创建共性。这将是一个只添加表和列的重构,保持读取兼容性与未更改的应用程序代码。

在此示例中,您将在“左侧”创建一个公用表,admin然后admin_custom将其连接起来。这将具有基金 ID、类型(因此您知道要加入哪个),如果可能的话,还有其他有用的公共列。

您还将在“左侧”创建一个公用表quant1quant1_cust然后从表连接。

然后,您将更改查询以使用公用表中的 Fund-ID 链接,将您的 UNION 子句替换为仅“公用表”(如果可能)或"Common Table" left outer join Legacy1 left outer join Legacy2.

我不明白这些表到底是什么,所以我无法帮助您进行合理的命名。(命名是设计中最重要的部分,您应该在问题中对此进行解释。)

但是这种方法对于我领导的一个主要政府项目非常有效,其中常用表是 DOCUMENT 和 DOC_ELEMENT。具有 8 种不同文档类型且没有预先存在的共性的树状结构文档。

在我们的案例中,DOCUMENT 被添加到 RFP、TENDER、PRICEPLAN 等的“左侧”,并提供了共性。

这不是完全的向后兼容性——您需要更改应用程序的 INSERT 代码。如果您要进行重构,您可能需要考虑将相同的表结构放入同一张表中

最好的办法是试验可能的结构,验证可能的性能,并确定需要哪些代码更改。然后,您可以选择一个轨迹。

于 2013-10-09T05:03:43.410 回答