0

我有两个表:D 字段 d1 和字段 d2 和 T 字段 s 这两个字段的类型为 Varchar2(255)

select d2 
FROM 
D , 
(select s from T where (s = 'val_1') OR (s='val_2') OR .. OR (s='val_n')  ) S
WHERE d1 LIKE CONCAT(CONCAT('%,',S.s),'%')

我的问题是数字 n 很大(优于 2500)

那么解决请求的时间大约是五分钟

有没有办法减少这个时间

4

2 回答 2

1

让我们从D. 这个 WHERE 子句...

WHERE d1 LIKE CONCAT(CONCAT('%,',S.s),'%')

……是致命的。这意味着查询需要探测. D1没有常规索引可以帮助查找两端都带有通配符的值。

现在让我们考虑T。这个 WHERE 子句...

 (s = 'val_1') OR (s='val_2') OR .. OR (s='val_n')

...显然其中包含 2500 多个元素。纯毒调。

尽管断言(在评论中)“表上没有索引”,但发布的创建表语句具有主键,因此有可用的索引。

但由于T似乎只有一列,列上的索引T.S没有任何区别:全快速索引扫描将与全表扫描一样快(或慢)。鉴于 S 是一个非常慢的 varchar2(255),因为该块不会有很多值。

由于已经说明的原因,索引D.D1是无关紧要的,所以我们再次将全表扫描作为唯一的访问路径。

那么我们希望的最佳执行计划是什么?就像是:

  1. T的全表扫描
  2. 过滤 S 的 2500+ 个值
  3. D的全表扫描
  4. TS 和 D.D1 的哈希连接

...除了那些通配符将意味着嵌套循环操作而不是哈希连接。

最后让我们考虑一下这个声明:

“解决请求的时间大约是五分钟”

调整中的单个帖子重要的是对经过的时间有一个合理的期望。在这种情况下,五分钟可能代表非常缓慢的响应或非常快速的响应。谁能告诉?我们当然不能。只有 OP 可以,因为只有他们才能访问数据并因此有能力回答这些问题:

  • 列的平均长度是D1多少D2
  • 表中有多少行D
  • 什么是合理的阅读它们?
  • 列的平均长度是S多少?
  • 表中有多少行T
  • 什么是合理的阅读它们?
  • Twhere有多少行S匹配 '%val_1%' 到 '%val_n%' ?
  • 有多少行 D匹配D1'%val_1%' 到 '%val_n%'?
  • 什么是匹配它们的合理时间?
  • 显示 D2 的所有相关值的合理时间是多少?
于 2013-07-17T18:23:37.663 回答
0

每个主键创建一个索引时都有索引。但是,在匹配字符串的开头使用带有“%”的 LIKE 会使索引变得无用。

但总的来说,超过 2500 个 OR 子句暗示了一个更根本的问题。必须生成大量 OR 子句,因为没有人会输入或编写这样的查询。在我看来,查询的那部分迁移到了生成查询的代码。

所以你应该退后一步,问自己这个问题,你真正想要什么行,这些行需要满足什么条件。如果 val_1 .. val_n 来自数据库外部,请考虑先将它们放入数据库。

于 2013-07-16T19:57:44.750 回答