我有两张桌子: D与字段d1和字段d2 和田地的T. 这两个字段的类型为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)
然后解决请求的时间大约是五分钟
是否有减少此时间的解决方案
答案 0 :(得分: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
上的索引无关紧要,因此我们再次将全表扫描作为唯一的访问路径。
那么我们希望的最佳执行计划是什么?类似的东西:
...除了那些通配符将意味着嵌套循环操作而不是散列连接。
最后让我们考虑一下这个陈述:
“解决请求的时间大约是五分钟”
调整中的单个帖子重要的是对经过的时间有合理的期望。在这种情况下,五分钟可能代表一种非常缓慢的反应或极快的反应。谁能说出来?我们当然不能。只有OP可以,因为只有他们可以访问数据,因此能够回答这些问题:
D1
和D2
的平均长度是多少? D
中有多少行? S
的平均长度是多少? T
中有多少行? T
中S
匹配'%val_1%'到'%val_n%'的行数是多少?D
D1
匹配'%val_1%'到'%val_n%'的行数{{1}}? 答案 1 :(得分:0)
每个主键创建索引时都有索引。但是,在匹配字符串开头使用带有“%”的LIKE会使索引无效。
但总的来说,拥有> 2500 OR条款暗示了一个更基本的问题。必须生成大量的OR子句,因为没有人会输入或编写这样的查询。在我看来,该部分查询已迁移到生成查询的代码。
所以你应该退后一步,问自己一个问题,你真正想要的行,行需要满足的条件。如果val_1 .. val_n来自数据库外部,请考虑首先将它们放入数据库。