我需要将两个具有相同列的表组合在一起,并在复杂的JOIN查询中使用结果,但它会大大降低性能。使用UNIONs的此查询的执行时间为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秒。如何解决性能问题?
答案 0 :(得分:0)
您可以对数据库进行“附加更改”,以创建UNIONED表之间的通用性。这将是一个重构只添加表格&列,保持与未更改的应用程序代码的读取兼容性。
在此示例中,您将在“admin
和admin_custom
左侧创建一个公用表格,然后将其加入。这将有基金ID,TYPE(所以你知道你加入了哪个),如果可能的话,还有其他有用的公共列。
您还可以在“quant1
和quant1_cust
左侧创建一个公用表格,然后从加入。
然后,您将更改查询以使用公用表中的Fund-ID链接,将UNION子句替换为“Common Table”(如果可能)或"Common Table" left outer join Legacy1 left outer join Legacy2
。
我不明白这些表格到底是什么,所以我无法帮助你明智地命名。 (命名是设计中最重要的部分,你应该在你的问题中对此进行解释。)
但是这种方法对我领导的一个重大政府项目非常有效,其中常见的表格是DOCUMENT和DOC_ELEMENT。具有8种不同文档类型且没有预先存在的通用性的树状结构文档。
在我们的案例中,DOCUMENT被添加到“RFP,TENDER,PRICEPLAN等”的左侧,并提供了共性。
这不是完全向后兼容性 - 您需要更改应用程序的INSERT代码。如果您正在进行重构,您可能需要考虑将相同的表结构放在同一个表中。
最好的办法是试验可能的结构,验证可能的性能,并确定需要哪些代码更改。然后你可以选择一个轨迹。
答案 1 :(得分: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
;