我有一个表,有大约1800万条记录。我必须在一次查询中读取整个表,因为所有记录都是在同一天创建的。所以,首先我定义了一个索引,我使用下面的命令对四列进行查询:
CREATE INDEX test_etl_index ON test_table(t_date,c_num,obc,bu);
创建索引后,我必须对c_num、obc、bu的每一列使用此查询。
SELECT t_date,
c_num,
pd,
pds,
uc,
obc,
t_id,
da,
ca,
db,
t_time,
ibc,
lc,
lt,
sts,
wd,
bu
FROM test_table
WHERE t_date = '20170628'
AND c_num IN (SELECT KEY
FROM c_g
WHERE g_id = 1);
但是,对于每列,查询大约需要8分钟,这是非常非常慢的!
您能告诉我如何更改查询以获得更好的性能吗?如有任何帮助,我们将不胜感激。
4条答案
按热度按时间tez616oj1#
根据您提供的信息,我们几乎无法提供任何建议。
除了修复
DATE
列的数据类型之外,因为将日期存储为字符串确实会使优化器感到困惑。预期的设置取决于 * 您的数据 *,这里有一些提示。
DATE列是选择性的
如果 predicate
date='20170628'
(或更好的col_date = date'2017-06-28
)只返回 * 很少的记录 *,那么您将从该列的索引中获益。您可以预期执行计划如下所示
请注意,Oracle * 在 hash join semi 中重写 * 您的
in (subquery)
,因此不需要手动重写查询。C_NUM是选择性的
相反,如果 predicate
c_num in (...
返回很少的记录,则在c_num
列上定义索引。您可以预期执行计划如下所示
无选择性
如果以上两种情况都不成立,则说明忘记了索引,您应该会看到一个HASH JOIN SEMI,它在18M表上不会花费太多时间
重要的一点是学习如何获取查询的execution plan,如何读取它,以及如何理解瓶颈在哪里。
lymnna712#
仅对date和c_num列创建索引,而不是(date,c_num,obc,bu);或者对date和c_num创建另一个索引,并将其称为idx 2
ruoxqz4g3#
问题解决了。
我分别在列上创建INDEX,如下所示:
然后运行查询。它运行得更快。
希望对其他人有用。
7gs2gvoe4#
使用存在而不是在()中
其中t_date = '20170628'且存在(从c_g中选择'x',其中g_id = 1且关键字=测试表.c_编号)