我有一个查询需要很长时间才能执行。表说明。这些表非常大,因此将在描述中给出相关列。所有列都是varchar。
表1-概述
pk-索赔id
记录数量-263万,
表2-注册
记录数量-250万
cols-索赔id(pk)、保单id、会员id
表3-成员
没有fo记录-2800万
cols-成员id(pk)、策略组id
表4-政策
没有fo记录-200万
cols-策略\u id,策略\u子策略\u常规\u类型\u id
表5-余额
没有记录-1200万。
柱
查询是
SELECT cg.CLAIM_ID,mem.Policy_group_ID ,
CAST(CASE when pol.policy_sub_general_type_id = 'PFL'
then (bal2.sum_insured - bal2.utilised_sum_insured)
when pol.policy_sub_general_type_id = 'PNF'
then (bal1.sum_insured - bal1.utilised_sum_insured)
end AS DECIMAL(10, 2) ) Balance_SI
FROM General cg
LEFT JOIN Enrol ce ON cg.CLAIM_ID = ce.CLAIM_ID
LEFT JOIN Member mem ON ce.MEMBER_ID = mem.MEMBER_ID
LEFT JOIN Policy pol ON pol.POLICY_ID = ce.POLICY_ID
LEFT join Balance bal1 ON bal1.MEMBER_ID = ce.MEMBER_ID
and bal1.MEMBER_ID is not null
LEFT join Balance bal2 ON bal2.Policy_group_ID = mem.Policy_group_ID
and bal2.Policy_group_ID is not null
GROUP BY cg.CLAIM_ID
解释语句显示
Select Type|table|Type|key|rows|Extra
_____________________________________
SIMPLE|cg |index|PRIMARY|2662233|Using Index
SIMPLE|ce |ref|index1|1|NULL
SIMPLE|mem|eq_ref|PRIMARY|1|using where
SIMPLE|pol|eq_ref|PRIMARY|1| Using Where
SIMPLE|bal1|ref|index2|3|Using Where
SIMPLE|bal2|ref|index1|1|using where
服务器参数
innodb\u缓冲池\u-10gb
innodb\日志\文件\大小-3gb
4核处理器
所有表和列都具有相同的排序规则和字符集,因此这不是排序规则问题。连接列也是varchar。explain语句显示(我假设)表索引良好。查询大约需要15分钟才能返回前50000行,这在此时是不可接受的。对于整个表,它在过去3小时内仍在运行,没有任何结果。不知道为什么会这样。请帮忙。
2条答案
按热度按时间xpcnnkqh1#
这还不是答案
我不清楚你的数据库模式。
我有很多问题和很多想法如何加快这个查询。
让我们看看你的第一部分:
您有“内联”函数调用,这会影响性能:
CAST, CASE, bal1.sum_insured - bal1.utilised_sum_insured, bal2.sum_insured - bal2.utilised_sum_insured
如果你的应用程序或任何你能接受不“格式化”的结果返回查询,我建议删除CAST
-它将在不影响返回的实际值的情况下稍微加快查询速度。您可以稍后在应用程序级别对这些值进行舍入。下一个是
CASE
,同样,如果你有你的应用程序级别(我希望),你可以返回原始数据,而不是转换的结果。我的意思是你可以返回3列:pol.policy_sub_general_type_id, bal1.sum_insured - bal1.utilised_sum_insured, bal2.sum_insured - bal2.utilised_sum_insured
而不是CASE
. 但我怀疑你甚至不需要这种优化。我待会再给你看。我有很多关于你的问题
JOIN
他也是。但既然你还没有回答德拉普的问题,我将把我的问题保留一段时间。让我们直接去查询我怀疑会返回几乎相同的数据,你需要和讨论细节以后如果你会有任何特定的问题。
x8goxv8g2#
对于初学者,您可以完全删除“cg”alias general表,除非您正在用于此处未显示的其他列。原因是,您可以直接从注册表中获得索赔id。只是删除额外的级别。
接下来,您的groupby只在声明中,但策略组id是select的一部分。你也打算按保险单汇总吗?一个索赔是否可以由多个保单组承保?如果没有,并且您只是想继续,您可以通过max(mem.policy\u group\u id)将其作为policy\u group\u id保存
正如strawberry所指出的,按笛卡尔结果的位置进行聚合/分组可能会给出错误的答案。
我还建议编辑你的帖子,并确认一些额外的细节,如余额表。你有一个总数基于“pfl”为“pnf”我们知道他们背后有具体的含义,但对我们来说没有任何意义。您的case/when正在从“bal1”和“bal2”别名中提取值。在这种情况下,特定的策略组没有输入余额表,而是落入某个“通用存储桶”或某个特定于单个策略的存储桶中?比如定期报道“x”,但你对“y”类有限制吗?
下面是更清晰的sql可读性,删除了general表。
最后,查看您的case/when和join on bal2 alias,您没有对成员id的引用,因此让我们向您展示您可能遇到的笛卡尔杀手。例如,联邦雇员属于一个政策组,有2万名雇员。现在您还有一个加入余额表的注册记录?是每个策略组一条记录,还是每个成员/策略组一条记录。如果是每个成员/策略,则每次尝试从bal2中获取值时,您都要遍历20k个余额记录。而余额表“bal1”的别名是每个成员id显式的。所以我知道这两个字段都在表中,这可能会让你很痛苦。
再次,请编辑您现有的职位,澄清细节和关系,特别是1:1对1:n