DB2 查询优化
Posted
技术标签:
【中文标题】DB2 查询优化【英文标题】:DB2 Query optimization 【发布时间】:2016-04-06 17:19:36 【问题描述】:全部, 在优化查询方面需要帮助:
有以下两个表格:
表 1 AdminId Policy Locationid CreateTimestamp
表 2 AdminId 策略 CreateTimestamp Detail1 Detail2 。详情50
表 2 是一个包含大量数据的大表。对于 Table1 中的每个记录,Table2 中可能有数千行。 要求是从具有 location = NY 的表 2 中获取最近一年的计数数据。 我在下面写了查询,但它没有优化,我无法运行它。 请建议如何优化此查询。提前致谢!
Select count(*) from Table2 T2 , Table1 T1 where T1.adminId = T2.adminId and
T1.policy = T2.policy and T1.location like ('℅NY℅') and
T2.createTimestamp > ( current Timestamp - 1 year)
【问题讨论】:
你真的有多个值存储在位置吗?这就是你需要通配符的原因吗? 是的,locationid 是一个 15 字节的字段,而 NY 位于中间,所以我必须使用通配符.. 【参考方案1】:您应该首先修改您的查询以使用 ANSI 样式的显式 JOIN 语法,例如
Select count(*) from Table2 T2
JOIN Table1 T1
ON T1.adminId = T2.adminId
and T1.policy = T2.policy
where T1.location like ('℅NY℅')
and T2.createTimestamp > ( current Timestamp - 1 year)
同时确保您为两个表的JOIN ON
条件和WHERE
条件所涉及的所有列创建了索引。
【讨论】:
你真的认为有一个不同的计划只是因为旧加入和新加入吗? 虽然我完全同意不应该使用旧式隐式连接,但这并不能解决性能问题。 如果他在使用单个连接时遇到性能问题,那么他遇到的问题比获得一个简单查询的计数更大。【参考方案2】:这可能是你的问题:
and T1.location like ('℅NY℅')
在大多数数据库中,这种类型的构造不允许您使用索引,因此查询无法正常执行。
如果字段中没有多个位置,则删除不必要的通配符。如果您拥有它们,那么您需要更改数据模型以将该数据正确地放入相关表中。切勿将逗号(或其他分隔符)分隔的列表存储在数据库的字段中。
如果您无法更改数据模型,您可以做的最好的事情是编写一个函数将数据拆分为某种类型的临时表,然后加入该表。在 Sql Server 中,我建议您通过 Google 查找 fn_split 以了解如何执行此操作。我不熟悉你会如何在 DB2 中做这种事情,但互联网上可能有一个类似的函数可供开始。
【讨论】:
实际上,有必要使用通配符作为位置,因为我有一个 15 字节的 locationid,而“NY”介于两者之间。这是查询需要很长时间执行的原因吗?它根本没有在生产中执行。我在大型机上工作,我目前正在使用 QMF 来执行这个查询。如果它运行良好,那么我会将它包含在我的代码中。感谢您的所有帮助! :-) 在大多数数据库中,where 条件开头的通配符意味着不能使用索引。但是,对于 DB2,您不确定这一点。如果位置 id 有 NY inteh 中心,它是在同一个地方吗?如果是这样,那么在开始时使用左、右、子字符串类型的函数可能比通配符更快。或者,如果您要经常查询此类事情,则可能值得在插入或更新时将该信息提取到单独的状态字段中,以便在执行选择时更轻松地查询。 我也尝试过使用 substr ,但查询仍然没有在 prod 中运行 .. 当我运行 d query 时,它会在 xwait 上运行很长时间,并显示以下错误消息:未成功执行,因为 DB2 资源超出限制 。资源名称 = ASUTIME ,限制 = 000000009【参考方案3】:如果标签被正确索引并且统计信息是最新的,那么这样的简单查询应该不会导致性能问题。 检查计划是否使用现有索引并且估计正确(完全错误的数字可能表示统计问题)。
我对 DB2 了解不多,您可以尝试将条件移动到两个派生表中,但这对于一个像样的优化器来说应该没什么区别:
Select count(*)
from
(
select adminId, policy
from Table1
where T1.location like ('℅NY℅') -- probably T1.location = '℅NY℅'
) T1
join
(
select adminId, policy
from Table2
where createTimestamp > ( current Timestamp - 1 year)
) T2
ON T1.adminId = T2.adminId
and T1.policy = T2.policy
【讨论】:
【参考方案4】:表 1:
AdminId | Policy | LocationId | CreateTimestamp
表 2:
AdminId | Policy | CreateTimestamp | Detail1 | Detail2 | ... | Detail50
我认为您的查询是:
SELECT COUNT(*)
FROM Table2 AS T2
INNER JOIN Table1 AS T1 ON T2.AdminId = T1.AdminId AND T2.Policy = T1.Policy
WHERE T1.Location LIKE ('%NY%') AND T2.CreateTimestamp > DATEADD(year,-1,GETDATE())
您仍然希望带有通配符的 LIKE 出现在 WHERE 子句中,您可以使用 DATEADD(year,-1,GETDATE()) 与您的时间戳进行比较,以查看记录是否已在最后创建年。
【讨论】:
问题是关于 DB2 的,原始语法在 DB2 中完全有效。 对将数据嵌入其他数据 NY 投反对票。 当然,但我真的不明白你在说“嵌入在纽约其他数据中的数据”是什么意思。可能是因为我将 LIKE 放在 where 子句中。虽然对我自己的学习来说,一个解释会很棒。以上是关于DB2 查询优化的主要内容,如果未能解决你的问题,请参考以下文章
如何针对 db2 数据库优化 SQL/Python 选择查询?
需要帮助优化涉及数百万条记录的非常慢的 DB2 SQL 查询