当过滤器只包含一个字母+通配符

时间:2016-05-25 22:33:43

标签: openldap

当具有子字符串索引的字段上使用一个字母的过滤器和通配符(*)时,我的OpenLDAP实例返回记录的速度很慢。当过滤器有多个字母时,搜索速度非常快。我的问题是为什么?

场景是OpenLDAP v.2.4.44,LMDB后端,OS X,130万条记录,索引设置为:

olcDbIndex: objectClass eq
olcDbIndex: cn eq,sub

如果搜索过滤器是'(cn = s *)',则查询需要很长时间,而如果过滤器是'(cn = sm *)'它的速度非常快。运行 slapindex 没有任何区别。

以下是一些数字,使用时间

$time ldapsearch -H ldap:/// -D cn=Manager,dc=xyz,dc=com -w secret -b dc=xyz,dc=com -s sub -z 5 '(cn=s*)' cn sn

-- some ldap records --

real    0m0.474s
user    0m0.001s
sys     0m0.002s

更改为'(cn = sm *)'会产生:

real    0m0.012s
user    0m0.001s
sys     0m0.003s

'(cn = smi *)'

real    0m0.012s
user    0m0.001s
sys     0m0.003s

事实上,一旦过滤器有多个字母和通配符,那些时间就会保持不变。

进一步调查,我发现在字母表中向下的结果会逐渐变长,但仅限于那个单字母搜索。

使用'(cn = a *)'给出:

real    0m0.012s
user    0m0.001s
sys     0m0.003s

'(CN = B *)'

real    0m0.046s
user    0m0.001s
sys     0m0.004s

此时,您可以看到用户和系统总是很快,所以从现在开始我将省略它们,并且只显示实时。因此:

'(cn=a*)' --> 0m0.012s
'(cn=b*)' --> 0m0.046s
'(cn=c*)' --> 0m0.105s
'(cn=d*)' --> 0m0.149s
'(cn=e*)' --> 0m0.174s
...
'(cn=m*)' --> 0m0.342s
...
'(cn=s*)' --> 0m0.523s
...
'(cn=z*)' --> 0m0.606s

但是,如果这些搜索中的任何一个都有一个额外的字母,它会恢复快速(平均0.012秒)。所以出于某种原因, slapd 需要很长时间才能找到第一个字母,但只有在使用一个字母时才会这样。

在进一步调查时,对'sn'属性(例如'sn = s *')进行过滤(未编入索引),使用一个字母+通配符过滤器时,会产生与索引'cn'属性相同的时间。因此,当过滤一个字母+通配符时, slapd 似乎忽略了'cn'属性上的子字符串索引。但是,添加第二个字母会使'cn'过滤器变快,而'sn'过滤器保持缓慢,这是预期的。

为什么会发生这种情况?如何解决?

1 个答案:

答案 0 :(得分:0)

发现此行为是设计使然。 OpenLDAP具有一个全局设置,用于控制子字符串索引的最小长度。在子字符串索引中索引的默认最小字符数为2.

如果您使用在线配置(OLC),您将在 man slapd-config 中找到该设置的说明:

  

olcIndexSubstrIfMinlen :< integer>
  指定subinitial和subfinal指数的最小长度。属性值必须至少包含这么多字符才能由索引函数处理。默认值为2.

或者,如果您使用传统的配置方法,您将在 man slapd.conf 中找到它的描述:

  

index_substr_if_minlen :< integer>
  指定subinitial和subfinal指数的最小长度。属性值必须至少包含这么多字符才能由索引函数处理。默认值为2.

man 页面另外说:

  

本节中描述的选项适用于所有后端,除非在后端定义中明确覆盖。

有谁知道在属性级别是否可以覆盖此行为?如果可以在比全局或每个后端更细粒度的级别指定子串最小和最大长度,那将是很好的。