Hi again,

I've completed my optimization on indices under high partition capacities. The results are in line and side by side to the old results. For those not interested in the exact optimization that took place skip down to the results.


The problem:
------------

Up to now duplicate keys (keys with many values) were stored using a TreeSet within the B+Trees of indices. Indices usually map some attribute value to an ID into the master table for an entry. The ID is a sequentially unique value assigned to the entry.

So if 100 people have initials AA then there would be 100 values in the TreeSet for the key 'AA' in the intials index. This would be serialized and deserialized to and from disk. At these low numbers there's really very little impact. However certain indices were seriously impacted like the objectClass index or the hierarchy based system index. Just imagine having 1 million entries of inetOrgPersons. The objectClass index would then have 1 million values in the TreeSet for the key 'inetOrgPerson'. This would seriously hurt performance from both a space and time perspective. It would essentially obfuscate the benefits of using BTree's in the first place with large numbers of entries.


Solution:
---------

What I did was add a configurable threshold parameter when instead of using a TreeSet to store duplicates another B+Tree was created and used within the same index database file. Right now the default value for this which these tests were conducted with is 1000. So after having 1000 duplicate values the server switches from using in memory TreeSets to on disk B+Trees for only storing values for that key.


Alex Karasulu wrote:
Hi all,

I've been testing the search performance boost gained from indexing
attributes before starting development on an optimization to improve
index performance and in memory size.  I thought I'd share these
dramatic results of my pre-optimization tests with you since they
clearly show the benefits of indices.

Before I do this let me list the characteristics of the hardware used
and my configuration settings:


-------------
Machine Setup
-------------

CPU: Dual Athlon MP 1900
OS: Linux 2.6.15
Mem: 2GB 266Mhz


--------------
ApacheDS Setup
--------------

ApacheDS: Stock RC4 (to be released pre-image) w/ modifications
  - Using 1024MB Memory
  - Indexed st and initials


----------
Data Setup
----------

Wrote a simple tool to generate random values for descent sized entries.
 The data sort of looks like this for a user entry:

    dn: uid=user.1,ou=users,dc=example,dc=com
    uid: user.1
    initials: yq
    description: cFocJATNuhlXisDCqGtY
    pager: FYyimqyZRW
    cn: HSGMzajYKmicUTe
    postalcode: WiXXA
st: xy street: kpCCqmrsCzkpdtHXWMfY
    l: KqmAXFYTrI
    objectclass: person
    objectclass: organizationalPerson
    objectclass: inetOrgPerson
    sn: nuymgOwpm
    homephone: PERamkCtsv
    mobile: vkIviOGNTC
    telephonenumber: 7248889026
    mail: pYvEoOjSnEymcWD
    givenname: IVHJZB
    postaladdress: crObexKoUTIFdzNHcZMr
    employeenumber: 1
    userpassword:: cGFzc3dvcmQ=

I started loading a partition up with these entries 100,000 of them at a
time then performing the following searches for all entries with
initials aa:

(1) index on initials but no cached entries
(2) index on initials with cached entries
(3) no index without cached entries

Here are the results at the various capacities:

---------------
100,000 Entries
---------------

    [cached] [indexed] [time (seconds)]

(1)    no       yes        3.30
                             2.37
(2)    yes      yes        0.72
                             0.76
(3)    no       no         30.63
                             42.08

search results = 153 entries
                   146

Notice that if #2 is total time for cached entries we can conclude that #1 - #2 is a descent measure of pulling from disk. So let's see what that number looks like:

Old: 2.58
New: 1.61



---------------
200,000 Entries
---------------

    [cached] [indexed] [time (seconds)]

(1)    no       yes        6.04
                             3.29
(2)    yes      yes        1.44
                             1.49
(3)    no       no         82
                             83

search results = 302 entries
                   297
#1 - #2 values:

Old: 4.60
New: 1.80



---------------
300,000 Entries
---------------

    [cached] [indexed] [time (seconds)]

(1)    no       yes        7.54
                             4.11
(2)    yes      yes        1.95
                             2.22
(3)    no       no         146
                             128

search results = 451 entries
                   435

#1 - #2 values:

Old: 5.59
New: 1.89



---------------
400,000 Entries
---------------

    [cached] [indexed] [time (seconds)]

(1)    no       yes        9.24
                             4.87
(2)    yes      yes        3.80
                             2.69
(3)    no       no         196
                             168

search results = 586 entries
                   577

#1 - #2 values:

Old: 5.44
New: 2.18



---------------
500,000 Entries
---------------

    [cached] [indexed] [time (seconds)]

(1)    no       yes        11.96
                              5.06
(2)    yes      yes        3.21
                             3.21
(3)    no       no         224
                             209

search results = 748 entries
                   706

#1 - #2 values:

Old: 8.75
New: 1.85


Besides these numbers I've noticed that adds are now faster and total garbage collection is lower. These were eyeballed figures. For example the adds would grow in time up to 28 minutes per 100K entries for those between 400K-500K. This has dropped down to 18 minutes.

Now it would be interesting to see what happens with these trends once the intials index converts from a TreeSet to a BTree for the values of the key 'aa'. So just to see we keep loading up the partition until there are over 1000 entries with initials 'aa'.

I'll report on this tomorrow as the server loads these entries.

I guess the conclusion here is that the optimization had a significant effect and is worth the additional complexity it introduced into the JDBM partition implementation. Here's the access times (#1-#2) as a
function of the number of entries:


Retrieval Times | 100K | 200K | 300K | 400K | 500K
--------------------------------------------------
Before:         | 2.58 | 4.60 | 5.59 | 5.44 | 8.75
After:          | 1.61 | 1.80 | 1.89 | 2.18 | 1.85


Before the optimization there seems to be a linear growth to access time whereas after the optimization the growth rate is almost unmeasurable above the noise.

-Alex

Reply via email to