我需要一些帮助才能提升这个SQL语句。执行时间约为125毫秒
在我的程序运行期间这个sql(更好:不同表格的结构相同的sqls)
将被称为300.000次。
表中的平均行数约为10.000.000行,每天将添加新行(更新/插入)和时间戳。这个特定出口计划的有趣数据在过去的1-3天内。也许这对创建索引很有帮助。我需要的数据是给定id的当前有效行和获取更新的forerunner数据行(如果存在)。
我们使用Oracle 11g数据库和Dot.Net Framework 3.5
要提升的SQL语句:
select
ID_SOMETHING, -- Number(12)
ID_CONTRIBUTOR, -- Char(4 Byte)
DATE_VALID_FROM, -- DATE
DATE_VALID_TO -- DATE
from
TBL_SOMETHING XID
where
ID_SOMETHING = :ID_SOMETHING
and ID_CONTRIBUTOR = :ID_CONTRIBUTOR
and DATE_VALID_FROM <= :EXPORT_DATE
and DATE_VALID_TO >= :EXPORT_DATE
order by
DATE_VALID_FROM asc;
我在这里上传了此查询的当前Explain-Plan。
我不是数据库专家,因此我不知道哪种索引类型最适合此要求。 我已经看到可以应用许多不同的可能索引类型。 也许Oracle Optimizer Hints也很有帮助。
有没有人有一个好主意来调整这个SQL或者能指出我正确的方向?
答案 0 :(得分:5)
解释计划看起来尽可能好,但这并不一定意味着什么。 Quassnoi提出的指数正是我的建议。
无论如何,在你的程序中做了300000个类似的查询让我问:这有必要吗?也许你可以用更少的查询达到相同的目标,每个查询都做得更多。
如果你不能避免这么多的查询,你应该至少使用预备语句。如果你使用LINQ,那就是你编译的语句。这样,您就可以避免解析开销,这可能是整体支出的一个相当大的部分,特别是对于这种简单的查询。
答案 1 :(得分:4)
创建综合索引:
CREATE INDEX ix_something_s_c_d ON tbl_something (id_something, id_contributor, date_valid_from)
不幸的是,您正在搜索两列范围内的常量,而不是两个常量范围内的列,因此最后一个字段的选择性不是很高。不过,它可以帮助订购。
答案 2 :(得分:1)
你说:
对此感兴趣的数据 特别是出口计划在于 过去1-3天。
这是否意味着您对DATE_VALID_FROM在过去三天内的行感兴趣?如果是这样,您可以从索引中获得更多欢乐:
create index something_idx
on tbl_something (date_valid_from, id_something, id_contributor, date_valid_to)
/
包括date_valid_to
意味着索引读取可以满足查询而不会触及表。 date_valid_from
的前导将所有可能感兴趣的行放在同一块索引空间中。
以上假设您的300,000次调用适用于id_something
和id_contributor
的各种不同值。如果这个假设是假的 - 说它们都是相同的id_contributor
,或者你连续执行50,000个同一个id_contributor
的调用 - 那么用(id_contributor, date_valid_from ...)
引导会更有意义。通常情况下,查询调优的业务逻辑细节对于找到满意的结果至关重要。哦,对不同的想法进行基准测试至关重要。
我同意AmmoQ的意见,即在一个过程中执行相同的语句300,000次听起来像一个RBAR实现,可能更适合面向集合的方法。