查询的运行时间极其不成比例。试图理解 RDBMS

Posted

技术标签:

【中文标题】查询的运行时间极其不成比例。试图理解 RDBMS【英文标题】:extremly disproportionate running time for query. Trying to understand RDBMS 【发布时间】:2015-05-29 15:52:53 【问题描述】:

我正在使用我们公司只有读取访问权限的客户数据库 (db2)。因此,我无法控制索引、模式等。我想强调这一点,因为可能还有我不知道在哪里的索引。所以我必须以不同的方式优化我们的查询。无论如何,我更感兴趣的是了解这些事情是如何工作的,而不是解决方法(尽管我也对此感兴趣)。我希望 DB 能够快速完成此类操作,但显然并非如此。或者,也许我遇到了一个严重的陷阱。

场景: 我剖析了我们的查询,并将其剥离为以下我无法理解的内容。让我们将此查询称为q1,其形式为

select c.cid, c.bid, c.ryear, t.tyear, td.nr
 from mySchema.cTable c
 join mySchema.dTable d on d.cid = c.cid
 join mySchema.ipTable ip on (ip.did = d.did and ip.type = 'type_s')
 join mySchema.tTable t on t.xtime = ip.xtime
 join mySchema.tdTable td on c.tdid = 'type_'||td.oid
where
 c.ryear = 2009
 and d.rr = 'ugk'
 and d.stat = 'stat#1'
;

此查询检索大约 8000 个条目,执行时间超过一分钟。

现在奇怪的部分是:如果我删除 where 子句中的任何一个条件,则执行查询所需的时间不到 2 秒。只是为了完整性:在我删除 ryear 的情况下,结果集返回大约 10000 个条目。如果我删除d.stat = 'stat#1',结果集包含大约45000个条目,如果我删除d.rr = 'ugk',我实际上得到的结果与我不删除它完全相同(即在这种特定情况下,这个条件对于结果来说是多余的设置)。

如果我同时具备所有 3 个条件,谁能解释我如何/为什么会发生这种巨大的时差?如果我简单地设置 2 个条件,然后在 cli 上 grep 为第三个条件,我会快得多。 DB到底在做什么?

注意:我正在使用 DbVisualizer 来运行我的查询。当我说在时间 x 中执行时,我指的是查询的执行时间,而不是获取时间(参见:http://www.dbvis.com/forum/thread.jspa?threadID=1536)。尽管如果我有所有 3 个语句(大约 10 分钟!)来检索与排除和 d.rr = 'ugk' 部分完全相同的结果,则提取时间也会急剧增加。对于我只有 2 个条件的情况,获取时间最多为 10 秒(即检索 45000 个条目时)。为了完整起见,如果我根本没有where,我会得到 130000 个条目(执行:1.8 秒,获取 28 秒)

我的问题:发生了什么事? where 子句中的单个语句能否将 dbs 执行计划破坏得如此糟糕?

p.s.:很抱歉,表/列的名称没有更具表现力,但出于显而易见的原因,我不得不对它们进行一些混淆。 p.p.s.:如果你能找到更合适的东西,我很乐意编辑标题。

【问题讨论】:

连接太多 + 有很多数据 + 非最佳条件 = 性能不佳 至少,c.tdid = 'type_' || td.oid 中的连接可能没有任何帮助(可能会使连接中索引的使用无效)。这对这里的行为有多大影响并不完全明显...... 一些额外的附注:1) 极端的运行时间可能表明索引统计信息已过时,如有必要,可以运行特定命令来更新这些信息(显然,您不能自己运行它)。 2)您可以查询information schema about indices,您几乎可以肯定需要此信息来智能地计划未来的查询。就此而言,DBVIS 也应该告诉您这些信息(作为 EXPLAIN 计划的一部分)。 【参考方案1】:

慢查询通常表示全表扫描。你一般一切都通过索引而不是表扫描来。 IBM Data Studio 中可能有工具可以帮助您确定表扫描的原因。

我建议以下索引:

SET SCHEMA mySchema;
CREATE INDEX cTable_ryear ON cTable(ryear) INCLUDE (cid, bid, tdid);
CREATE INDEX dTable_rr_stat_cid ON dTable(rr, stat, cid) INCLUDE (did);
CREATE INDEX ipTable_did_type ON ipTable(did, type) INCLUDE (xtime);
CREATE INDEX tTable_xtime ON tTable(xtime) INCLUDE (tyear);

可能还有一种方法可以优化对 tdTable 的访问。

【讨论】:

我说的第一件事是,我只有读取权限。因此我无法创建索引。 @dingalapadum - 在某些时候,您要么必须接受按原样运行事物的成本,要么花费资源(数据库空间)。如果这通常运行,您的 DBA 应该能够为您提供帮助。【参考方案2】:

你能告诉我们有哪些索引(SYSIBM.SYSINDEXES)吗?

也许您可以使用 WITH 又名临时表将查询分成 2...

【讨论】:

以上是关于查询的运行时间极其不成比例。试图理解 RDBMS的主要内容,如果未能解决你的问题,请参考以下文章

启动屏幕显示不成比例

当包含它的 DIV 类的大小正确时,如何纠正不成比例地拉伸的图像?

背景和菜单栏在宽屏上变得不成比例......我不想要这个

对运维的理解以及看法

RDBMS 中的临时查询是啥?

查询 HIVE 元数据