Incrementally Maintaining Run-length Encoded …abhijeet/papers/abhijeetIDEAS...Incrementally...

9
Incrementally Maintaining Run-length Encoded Attributes in Column Stores Abhijeet Mohapatra Stanford University [email protected] Michael Genesereth Stanford University [email protected] ABSTRACT Run-length encoding is a popular compression scheme which is used extensively to compress the attribute values in column stores. Out of order insertion of tuples potentially degrades the compres- sion achieved using run-length encoding and consequently, the per- formance of reads. The in-place insertions, deletions and updates of tuples into a column store relation with n tuples take O(n) time. The linear cost is typically avoided by amortizing the cost of up- dates in batches. However, the relation is decompressed and sub- sequently re-compressed after applying a batch of updates. This leads to added time time complexity. We propose a novel index- ing scheme called count indexes that supports O(log n) in-place insertions, deletions, updates and look ups on a run-length encoded sequence with n runs. We also show that count indexes efficiently update a batch of tuples requiring almost a constant time per up- dated tuple. Additionally, we show that count indexes are optimal. We extend count indexes to support O(log n) updates on bitmapped sequences with n values and adapt them to block-based stores. Categories and Subject Descriptors H.2.2 [Database Management]: Physical Design; H.3.1 [Information Storage and Retrieval]: Content Analysis and Indexing General Terms Algorithms, Theory, Performance Keywords column store, run-length encoding, incremental maintenance, in- place updates, indexing 1. INTRODUCTION Since Stonebraker et al’s seminal paper [20] in 2005, column stores have become the preferred platform for data warehousing and analytics. A case study in [16] shows that present enterprise systems are best served by column stores. Although column stores Permission to make digital or hard copies of part or all of this work for personal or classroom use is granted without fee provided that copies are not made or distributed for profit or commercial advantage and that copies bear this notice and the full citation on the first page. Copyrights for components of this work owned by others than ACM must be honored. Abstracting with credit is permitted. To copy otherwise, to republish, to post on servers or to redistribute to lists, requires prior specific permission and/or a fee. IDEAS12 2012, August 8-10, Prague [Czech Republic] Editors: Bipin C. Desai, Jaroslav Pokorny, Jorge Bernardino Copyright c 2012 ACM 978-1-4503-1234-9/12/08 $15.00 have recently received increased attention, the concept of decom- posed storage [5] dates back to the 1980s. [1] presents an excel- lent overview of the column store technology starting from the de- composed storage model [5]. Column stores support fast reads of data by vertically partitioning a relation and efficiently compress- ing attribute value using techniques such as run-length encoding and bitmap-encoding. The performance of the reads depends on the compression achieved. It has been shown in [17] that the compres- sion schemes such as run-length encoding and bitmap encoding are sensitive to the ordering of tuples. Hence, out of order insertions of the tuples potentially degrade the compression achieved and con- sequently, the performance of the reads. Therefore in order to in- crementally maintain relations while achieving good compression, column stores require the support for efficient in-place or offset- based inserts, deletes and updates of the tuples. On an average, the time taken to insert or delete a tuple at a given offset is linear in the number of the tuples of a relation. This is because, in addition to the updated tuple, the storage keys or iden- tifiers of the successive tuples have to be updated as well. In this paper, we consider the problem of efficiently supporting in-place insertions, deletions and updates of tuples in column stores. Previ- ous work in [3, 13, 15, 20] have proposed different techniques to amortize the cost of applying updates to a column store relation in batches. The central theme underlying these techniques (which are discussed in Section 4) is to buffer the updates in a differential store and later merge the updates with a read-optimized store using a ta- ble scan. Although such a differential update mechanism amortizes the time to apply updates in bulk, it does not avoid the linear cost of a table scan. In addition, the tuples in the read-optimized store are decompressed and subsequently re-compressed after applying the updates. This requires additional time. We show that we can support in-place inserts, deletes and updates of tuples in a column store relation in time that is sub-linear in the number of tuples and thus avoid a linear scan of the tuples. In this paper, we study the problem of efficiently updating run-length encoded attributes and extend our solution to bitmapped attributes. Updating run-length encoded attributes: Tuples of a relation in a column store are ordered by sort keys and every attribute is stored separately as a sequence of values. These sequences are either run-length encoded or bitmap encoded. The bitmapped at- tributes are subsequently run-legth encoded to save space. The run-length encoding scheme compresses successive repetitions of values or runs in a sequence. A run of a value v can be succinctly represented either as a (v,n) or a (v,o) pair, where n is the run- length and o is the offset of the last (or the first) occurrence of v in the run. For presentation purposes, we shall call the former rep- resentation of runs as count-based and the latter representation as offset-based. We illustrate the two representation schemes using

Transcript of Incrementally Maintaining Run-length Encoded …abhijeet/papers/abhijeetIDEAS...Incrementally...

Incrementally Maintaining Run-length Encoded Attributesin Column Stores

Abhijeet MohapatraStanford University

[email protected]

Michael GeneserethStanford University

[email protected]

ABSTRACTRun-length encoding is a popular compression scheme which isused extensively to compress the attribute values in column stores.Out of order insertion of tuples potentially degrades the compres-sion achieved using run-length encoding and consequently, the per-formance of reads. The in-place insertions, deletions and updatesof tuples into a column store relation with n tuples take O(n) time.The linear cost is typically avoided by amortizing the cost of up-dates in batches. However, the relation is decompressed and sub-sequently re-compressed after applying a batch of updates. Thisleads to added time time complexity. We propose a novel index-ing scheme called count indexes that supports O(log n) in-placeinsertions, deletions, updates and look ups on a run-length encodedsequence with n runs. We also show that count indexes efficientlyupdate a batch of tuples requiring almost a constant time per up-dated tuple. Additionally, we show that count indexes are optimal.We extend count indexes to support O(log n) updates on bitmappedsequences with n values and adapt them to block-based stores.

Categories and Subject DescriptorsH.2.2 [Database Management]: Physical Design; H.3.1 [InformationStorage and Retrieval]: Content Analysis and Indexing

General TermsAlgorithms, Theory, Performance

Keywordscolumn store, run-length encoding, incremental maintenance, in-place updates, indexing

1. INTRODUCTIONSince Stonebraker et al’s seminal paper [20] in 2005, column

stores have become the preferred platform for data warehousingand analytics. A case study in [16] shows that present enterprisesystems are best served by column stores. Although column stores

Permission to make digital or hard copies of part or all of this work forpersonal or classroom use is granted without fee provided that copies are notmade or distributed for profit or commercial advantage and that copies bearthis notice and the full citation on the first page. Copyrights for componentsof this work owned by others than ACM must be honored. Abstracting withcredit is permitted. To copy otherwise, to republish, to post on servers or toredistribute to lists, requires prior specific permission and/or a fee.IDEAS12 2012, August 8-10, Prague [Czech Republic]Editors: Bipin C. Desai, Jaroslav Pokorny, Jorge BernardinoCopyright c©2012 ACM 978-1-4503-1234-9/12/08 $15.00

have recently received increased attention, the concept of decom-posed storage [5] dates back to the 1980s. [1] presents an excel-lent overview of the column store technology starting from the de-composed storage model [5]. Column stores support fast reads ofdata by vertically partitioning a relation and efficiently compress-ing attribute value using techniques such as run-length encodingand bitmap-encoding. The performance of the reads depends on thecompression achieved. It has been shown in [17] that the compres-sion schemes such as run-length encoding and bitmap encoding aresensitive to the ordering of tuples. Hence, out of order insertions ofthe tuples potentially degrade the compression achieved and con-sequently, the performance of the reads. Therefore in order to in-crementally maintain relations while achieving good compression,column stores require the support for efficient in-place or offset-based inserts, deletes and updates of the tuples.

On an average, the time taken to insert or delete a tuple at a givenoffset is linear in the number of the tuples of a relation. This isbecause, in addition to the updated tuple, the storage keys or iden-tifiers of the successive tuples have to be updated as well. In thispaper, we consider the problem of efficiently supporting in-placeinsertions, deletions and updates of tuples in column stores. Previ-ous work in [3, 13, 15, 20] have proposed different techniques toamortize the cost of applying updates to a column store relation inbatches. The central theme underlying these techniques (which arediscussed in Section 4) is to buffer the updates in a differential storeand later merge the updates with a read-optimized store using a ta-ble scan. Although such a differential update mechanism amortizesthe time to apply updates in bulk, it does not avoid the linear costof a table scan. In addition, the tuples in the read-optimized storeare decompressed and subsequently re-compressed after applyingthe updates. This requires additional time. We show that we cansupport in-place inserts, deletes and updates of tuples in a columnstore relation in time that is sub-linear in the number of tuples andthus avoid a linear scan of the tuples. In this paper, we study theproblem of efficiently updating run-length encoded attributes andextend our solution to bitmapped attributes.

Updating run-length encoded attributes: Tuples of a relationin a column store are ordered by sort keys and every attribute isstored separately as a sequence of values. These sequences areeither run-length encoded or bitmap encoded. The bitmapped at-tributes are subsequently run-legth encoded to save space. Therun-length encoding scheme compresses successive repetitions ofvalues or runs in a sequence. A run of a value v can be succinctlyrepresented either as a (v, n) or a (v, o) pair, where n is the run-length and o is the offset of the last (or the first) occurrence of vin the run. For presentation purposes, we shall call the former rep-resentation of runs as count-based and the latter representation asoffset-based. We illustrate the two representation schemes using

the following example.

Example 1.1. Consider the sequence of values a, a, b, b, b, a, a,a, b, b. If we use the count-based representation of runs to encodethis sequence we would get (a, 2), (b, 3), (a, 3), (b, 2). Instead, ifwe use the offset-based representation of runs, the sequence wouldbe encoded as (a, 2), (b, 5), (a, 8), (b, 10).

Each representation scheme has its advantages and disadvan-tages. Since the offsets of the runs increase monotonically, the val-ues in the offset-based representation can be efficiently looked upusing augmented Binary Search Trees [2, 10, 12] in time that is log-arithmic in the number of the runs. However, if a run is inserted ordeleted, the offset of every successive run must be updated as well.Hence, the time taken to update a run-length encoded sequence islinear in the number of runs using the offset-based representation.

In contrast to the offset-based representation, a run can be in-serted or deleted using the count-based representation of a run-length encoded sequence in constant time if the offset of updatedrun is known. However, in order to look up a value at a given off-set, the offset of the preceding run must be computed as well. Sincethe run-lengths are not monotonic in general, the variants of binarytrees cannot be used to efficiently look up the value at a given off-set. Hence, the time to look-up a value in a run-length encodedsequence is linear in the number of runs using the count-based rep-resentation.

Thus choosing between the offset-based and the count-based rep-resentation of runs trades-off the time taken to look up and to up-date runs of values in a sequence. We summarize this trade-offin Table 1. In this paper, we show that we can leverage auxiliarydata structures along with an appropriate choice of a representationscheme to optimize this trade-off. Prior work [4, 6, 8, 9, 11, 14,19, 21, 22] on spatio-temporal aggregation for range queries hasstudied the problem of incrementally maintaining the partial sumsfor an array. However, the proposed data structures are not dy-namic. For instance, operations such as the in-place insertions andthe deletions of new array values are not supported. We distinguishcount indexes from the prior work on incrementally maintainingspatio-temporal aggregates in Section 4.

Table 1: Trade-off between the look up and update complexityfor run-length encoded sequences

n = number of the runs in the sequence

Representation Scheme Cost of operationLook up Update

Count-based O(n) O(1)Offset-based O(log n) O(n)

Contributions: We consider the problem of efficiently updatingrun-length encoded attributes as a first step towards efficiently up-dating column stores. We propose a novel indexing scheme calledcount indexes (in Section 2) that supports offset-based look ups aswell as updates in a run-length encoded sequence with n runs inO(log n) time. Thus, count indexes efficiently trade-off the timeto look up a value in a sequence with the time taken to update thesequence. We generalize count indexes (in Section 3) to efficientlyupdate bitmap encoded columns. Our contributions in this papercan be summarized as follows:

1. In Section 2.1, we describe a procedure to efficiently createcount indexes on a sequence with n runs in O(n) time.

2. In Sections 2.2 and 2.3, we show that count indexes supportoffset-based look ups and in-place insertion, deletion and up-date of runs in O(log n) time. We also show that a sequenceof k runs can be inserted into a count index on n runs inO(k + log n) time, thus lowering the time complexity of up-dating a batch of tuples using the techniques proposed in [3,13, 15, 20].

3. In Section 2.4 we show that the problem of incrementallymaintaining a run-lenth encoded sequence with n runs re-quires Ω(log n) time. Hence our technique of incremen-tally maintaining run-length encoded attributes using countindexes is optimal.

4. In Section 3, we extend count indexes to support O(log n)updates on bitmap encoded sequences of size O(n). We alsoadapt count indexes to block-based stores and present thecorresponding algorithms for inserting and deleting runs.

2. COUNT INDEXESIn Section 1, we observed that choosing a particular represen-

tation scheme to run-length encode a sequence trades-off the timetaken to look-up and to update a value at a supplied offset. In thissection, we present a novel indexing scheme called count indexesthat optimizes this trade-off. We define a count index as follows.

Definition 2.1. A count index is a binary tree on a sequence ofintegers. The integers are stored in the leaf nodes. Every interiornode in the count index stores the sum of its children’s values. Thusthe root of the count index stores the total sum of integers in thesequence.

10

a

2

b

3 3 2

a b

5 5

Figure 1: Count index on the sequence a, a, b, b, b, a, a, a, b, b

Given a run-length encoded sequence with n runs, we can look up or update runs of values atspecified o!sets using count indexes in O(log n) time. In the remainder of this section we discussalgorithms for index creation, look up and maintenance.

2.1 Index Creation

As discussed above, a count index is a binary tree on a sequence of integers. Every node in a countindex stores the the sum of the values of its children. To construct a count index on a sequence of nintegers, we divide the integers into groups of two. If n is odd, we create a group for the last count.We then compute the sum of the counts of the integers in each of the !n

2 " groups and recursivelybuild the count index on these !n

2 " sums. The detailed algorithm is presented in Figure 2. Thepointers to the parent, left and the right children of a node are stored in parent, lchild and rchildrespectively.

3.1 Index Creation

Consider an attribute with n runs. The n !value, count" pairs constitute the

leaves of the count index. Each node in the count index consists of two fields:

its count (ctr) and the counts of its children (lctr and rctr). For leaf nodes,

lctr = rctr = ctr. If a node has only one child, count of its other child is set

to 0. We describe below an algorithm to create a count index over n counts

represented as leaves [ci].

Algorithm 1 Creating a count index over n counts

CreateIndex ([ci], n)

if n = 1 thenreturn ci

elsefor i = 1 to n # 1 do

j $ i+12

dj.parent $ dj

dj.lchild $ ci dj.rchild $ ci+1

dj.count = ci.count + ci+1.countci.parent = ci+1.parent $ dj

i $ i + 2end forif n % 0 (mod 2) then

return CreateIndex ([di],n2)

elsedj.parent $ dj

dj.count = ci.countdj.lchild $ ci dj.rchild $ NULLci.parent $ dj

return CreateIndex ([di],n+1

2)

end ifend if

The algorithm proceeds by dividing the n leaves into groups of two. If

7

Figure 2: Algorithm to create a count index on a sequence of n integers

Time Complexity: In the first pass, we divide n integers into groups of two and compute thesum of the integers in each group. This takes n units of time. Similarly, the second pass takes !n

2 "

4

Figure 1: Count index on the sequence a, a, b, b, b, a, a, a, b, b

Figure 1 shows a count index on the sequence given in Exam-ple 1.1. While the count index is constructed on the run lengthsonly, we display the values (a and b) as well for presentation pur-poses. The root node in Figure 1 stores the number of values in thesequence (= 10).

Given a run-length encoded sequence with n runs, we can lookup or update runs of values at specified offsets using count indexesin O(log n) time. In the remainder of this section we discuss thealgorithms for index creation, look up and maintenance.

2.1 Index CreationAs discussed above, a count index is a binary tree on a sequence

of integers. Every node in a count index stores the the sum of thevalues of its children. To construct a count index on a sequence ofn integers, we divide the integers into groups of two. If n is odd,we create a group for the last count. We then sum the counts of theintegers in each of the dn

2e groups and recursively build the count

index on these dn2e sums. The detailed algorithm is presented in

Figure 2. The pointers to the parent, the left and the right childrenof a node are stored in parent, lchild and rchild respectively.

10

a

2

b

3 3 2

a b

5 5

Figure 1: Count index on the sequence a, a, b, b, b, a, a, a, b, b

Given a run-length encoded sequence with n runs, we can look up or update runs of values atspecified o!sets using count indexes in O(log n) time. In the remainder of this section we discussalgorithms for index creation, look up and maintenance.

2.1 Index Creation

As discussed above, a count index is a binary tree on a sequence of integers. Every node in a countindex stores the the sum of the values of its children. To construct a count index on a sequence of nintegers, we divide the integers into groups of two. If n is odd, we create a group for the last count.We then compute the sum of the counts of the integers in each of the !n

2 " groups and recursivelybuild the count index on these !n

2 " sums. The detailed algorithm is presented in Figure 2. Thepointers to the parent, left and the right children of a node are stored in parent, lchild and rchildrespectively.

3.1 Index Creation

Consider an attribute with n runs. The n !value, count" pairs constitute the

leaves of the count index. Each node in the count index consists of two fields:

its count (ctr) and the counts of its children (lctr and rctr). For leaf nodes,

lctr = rctr = ctr. If a node has only one child, count of its other child is set

to 0. We describe below an algorithm to create a count index over n counts

represented as leaves [ci].

Algorithm 1 Creating a count index over n counts

CreateIndex ([ci], n)

if n = 1 thenreturn ci

elsefor i = 1 to n # 1 do

j $ i+12

dj.parent $ dj

dj.lchild $ ci dj.rchild $ ci+1

dj.count = ci.count + ci+1.countci.parent = ci+1.parent $ dj

i $ i + 2end forif n % 0 (mod 2) then

return CreateIndex ([di],n2)

elsedj.parent $ dj

dj.count = ci.countdj.lchild $ ci dj.rchild $ NULLci.parent $ dj

return CreateIndex ([di],n+1

2)

end ifend if

The algorithm proceeds by dividing the n leaves into groups of two. If

7

Figure 2: Algorithm to create a count index on a sequence of n integers

Time Complexity: In the first pass, we divide n integers into groups of two and compute thesum of the integers in each group. This takes n units of time. Similarly, the second pass takes !n

2 "

4

Figure 2: Algorithm to create a count index on a sequence of nintegers [ci]

Time Complexity: In the first pass, we divide the n integers intogroups of two and compute the sum of the integers in each group.This takes n units of time. Similarly, the second pass takes dn

2e

units of time, the third pass takes dn4e units of time and so on. The

algorithm terminates after log n passes. The time complexity of theindex creation algorithm is therefore O(n + n

2+ n

4+ . . . + 1) =

O(2× n) = O(n).In Section 1, we observed that choosing one representation of

a run-length encoded sequence over the other trades-off the timetaken to update the sequence with the time taken to look up valuesat the supplied offsets. In the remainder of the section, we showthat count indexes optimize this trade-off by supporting O(log n)offset based look ups and updates on a sequence with n runs.

2.2 Index Look UpThe run lengths in a run-length encoded sequence are not mono-

tonic in general. Therefore we cannot directly perform a binarysearch on the run lengths to look up the leaf node corresponding toa given offset. However, if we start at the root of the count index,we can determine which of its children contains the leaf node cor-responding to the given offset in constant time. Suppose we wantto look up the value at offset p. Let the counts of the left child andthe right child of the root be lv and rv respectively. If p ≤ lv , thevalue at the offset p is located in the left child of the root. Other-wise, the value at the offset p is located in the right child. The leftor the right child of the root can be looked up in a similar manner.The look up procedure terminates when we arrive at the leaf whichcorresponds to the supplied offset. Thus the look up procedure ter-minates in time that is proportional to the height of the count index.The detailed algorithm for looking up values in a count index ispresented in Figure 3.

To illustrate how the look-up algorithm works, let us revisit thecount index (Figure 1) on the sequence given in Example 1.1. Sup-pose we want to look up the value at the 8th position from the startof the sequence. We look up the counts of the left and right childrenof the root of the count index. The count of the left child (= 5) isless than 8. Therefore, we look up the value at the offset 3 (= 8 - 5)in the right child (say r) of the root. Since the count of the left child

units of time, the third pass takes !n4 " units of time and so on. The algorithm terminates after log

n passes. The time complexity of the index creation algorithm is therefore O(n+ n2 + n

4 + . . .+1) =O(2 # n) = O(n).

In Section 1, we observed that choosing one representation of a run-length encoded sequenceover the other trades o! the time taken to update the sequence with the time taken to look upvalues given their o!sets. We show that count indexes optimize this trade-o! by supporting O(logn) o!set based look ups and updates on a sequence with n runs.

2.2 Index Look Up

The run lengths in a run-length encoded sequence are not monotonic in general. Therefore wecannot directly perform a binary search on the run lengths to look up the leaf node correspondingto a given o!set. However, if we start at the root of the count index, we can determine which ofits children contains the leaf node corresponding to the given o!set in constant time. Suppose wewant to look up the value at o!set p. Let the counts of the left child and the right child of theroot be lv and rv respectively. If p $ lv, the value at o!set p is located in the left child of the root.Otherwise, the value at o!set p is located in the right child. We can now look up the left or theright child of the root in a similar manner. The look up procedure terminates when we arrive ata leaf that corresponds to the supplied o!set. Thus the look up procedure terminates in time thatis proportional to the height of the count index. The detailed algorithm for looking up values in acount index is presented in Figure 3.

groups. For each group, we compute the sum of the counts of its members.

We recurse on these !n2" groups. We note that the first step of index creation

takes n time units, the second step takes !n2" time units and so on. Therefore

the time complexity of index creation is n + n2

+ n4

+ . . . = O(n). The height

of this index is O(log n).

3.2 Index Lookup

As discussed in section 2, column stores should support e!cient look up

attribute values based on run positions (or storage keys as described by [1]).

In this section we show that count indexes support O(log n) look ups where

n is the number of runs in an attribute and describe below an algorithm for

the same. The algorithm searches for the attribute value at position p in the

count index rooted at node.

Algorithm 2 Look up procedure in Column Stores

SearchCountIndex (p, node)

if node has no children thenreturn value at node

elselchild # left child of nodev # value at lchildif v > p then

SearchCountIndex (p, lchild)else

SearchCountIndex (p $ v, rchild)end if

end if

To illustrate how the look up procedure works, let us revisit the count

8

Figure 3: Algorithm to look-up values in a count index

To illustrate how the look-up algorithm works, let us revisit the count index (Figure 1) on thesequence given in Example 1.1. Suppose we want to look-up the value at the 8th position from thestart of the sequence. We look up the counts of the left and right children of the root of the countindex. Since the count of the left child (= 5) is less than 8, we look-up the value at o!set 3 (=8 - 5) in the right child of the root. Since the count of the left child is 3, our look up procedureterminates and returns the value a. The look-up procedure is shown in Figure 4.

Proof of correctness: We can establish the correctness of the look up algorithm shown inFigure 3 using induction on the height of the count index.

Base case: (Index with a root and 2 children i.e. height = 2) Suppose we want to look up thevalue in the pth position from the start of the sequence. Let lv and rv be the counts of the left andright children of the root node. If the o!set is positive and less than the size of the sequence, wehave:

1 $ p $ lv + rv (1)

5

Figure 3: Algorithm to look-up values in a count index

of r is 3, our look up procedure terminates and returns the value a.The look-up procedure is shown in Figure 4.

key = 3

a

2

b

3 3 2

a b

5

10

5

key = 8

Figure 4: Example of a look-up on a count index

Therefore, either p ! lv or p " lv ! rv.Inductive Hypothesis: We assume that the look up algorithm correctly returns the value at

any given o!set in a count index of height ! k.Induction Step: Suppose we look-up the value at the o!set p in a count index of height k +1.

Let lv and rv be the counts of the left and right children of the root node. Following the argumentmade in the base case, either p ! lv or p " lv ! rv. Since the children of the root node at a heightof k, the look up algorithm correctly returns the value at the o!set p.

Time Complexity: Consider a count index on a sequence of n integers. The algorithm inFigure 3 examines exactly one node at any level in the count index. If the height of the count indexis h, the time complexity of the look up procedure is O(h). Using Claim 2.3 we show that theheight h of a count index with n leaves is O(log n). Therefore count indexes support o!set-basedlook ups over a run-length encoded sequence in time that is logarithmic in the number of runs.

Supporting Range Predicates: Given a count index with n leaves, we can look up thevalues within a given range of o!sets in O(log n) time by creating links between the neighboringleaf nodes. Suppose we require values within the o!sets p and q from the start (p ! q). We lookup the value at o!set p using the algorithm shown in Figure 3. On reaching the leaf node thatcorresponds to the o!set p, we traverse the leaf’s neighbors on the right till we reach the leaf nodecorresponding to the o!set q.

2.3 Index Maintenance

It is essential for any index to be e"ciently updatable when new values are inserted or old valuesare deleted. When values in a sequence are updated, the corresponding count index is a!ected inone of the following ways:

1. The count of an existing leaf node is updated.

2. A new leaf node is inserted or an existing leaf node is deleted from the count index.

It is easy to handle Case 1 by updating the ancestors of the leaf node in time that is logarithmicin the number of runs in the sequence. However, the count index can be potentially unbalancedby Case 2. Since the counts of the leaf nodes are not monotonic, we cannot use traditional treerotation schemes that are used to balance AVL trees [2] and Red-Black trees [12]. In this section,we discuss techniques to e"ciently balance a count index when new values are inserted or old valuesare deleted. We note that in all of the examples which follow, we discuss inserts and deletes of singlevalues or counts into a count index. We can, however, use the index update procedures describedbelow to insert or delete runs of any length (# 1).

Deletions: Suppose we want to delete a leaf from a count index. There are two cases dependingon whether the leaf has a sibling or not.

6

Figure 4: Example of a look up on a count index

Proof of Correctness: We can establish the correctness of thelook up algorithm shown in Figure 3 using induction on the heightof the count index.

Base Case: (Count index with a root and 2 children i.e. height =2) Suppose we want to look up the value in the pth position fromthe start of the sequence. Let lv and rv be the counts of the left andright children of the root node. If the offset is positive and less thanthe size of the sequence, we have:

1 ≤ p ≤ lv + rv (1)

Therefore, either p ≤ lv or p− lv ≤ rv .Inductive Hypothesis: We assume that the look up algorithm

correctly returns the value at any given offset in a count index ofheight ≤ k.

Induction Step: Suppose we look up the value at the offset p ina count index of height k + 1. Let lv and rv be the counts of theleft and the right children of the root node. Following the argumentmade in the base case, either p ≤ lv or p − lv ≤ rv . Since thechildren of the root node are at a height of k, the look up algorithmcorrectly returns the value at the offset p.

Time Complexity: Consider a count index on a sequence of nintegers. The algorithm in Figure 3 examines exactly one node atany level of the count index. If the height of the count index ish, the time complexity of the look up procedure is O(h). UsingClaim 2.3 (which is presented later) we show that the height h ofa count index with n leaves is O(log n). Therefore count indexessupport offset based look ups over a run-length encoded sequencein time that is logarithmic in the number of the runs.

Supporting Range Predicates: Given a count index with n leafnodes, we can also look up the values within a supplied range ofoffsets in O(log n) time by creating links between the neighboringleaf nodes. Suppose we require values in between the offsets p andq from the start (p ≤ q). We look up the value at the offset p usingthe algorithm shown in Figure 3. On reaching the leaf node that

corresponds to the offset p, we traverse the leaf’s neighbors on theright till we reach the leaf node corresponding to the offset q.

2.3 Index MaintenanceIt is essential for any index to be efficiently updatable when new

values are inserted or old values are deleted. When values in asequence are updated, the corresponding count index is affected inone of the following ways:

1. The count of an existing leaf node is updated.

2. A new leaf node is inserted or an existing leaf node is deletedfrom the count index.

It is easy to handle Case 1 by updating the ancestors of the leafnode in time that is proportional to the height of the count index.However, the count index can be potentially unbalanced by Case 2.Since the counts of the leaf nodes are not monotonic, we cannot usetraditional tree rotation schemes which are used to balance AVLTrees [2] and Red-Black Trees [12]. In this section, we discusstechniques to efficiently balance a count index when new valuesare inserted or old values are deleted. We note that in all of theexamples which follow, we discuss the insertion and the deletionof single values or counts into a count index. We can, however,use the index update procedures described below to insert or deleteruns of any length (≥ 1).

Deletions: Suppose we want to delete a leaf from a count index.There are two cases depending on whether the leaf has a sibling ornot.

1

9

1

1

1 3

4

8

3 1

4

Figure 5: Count index on a sequence with five run-lengths: 1, 3, 3, 1 and 1

1. (Leaf has no siblings): In this case, we delete the leaf and its ancestors. If the new root hasonly one child, we make its child the new root node and iterate down the tree.

(b) Count Index after deletion

1 3

4

8

3

4

1

1

1

9

(a) Deleting a leaf that has no sibling

1 3

4

8

3 1

4

1 1 3

4

7

3

3

(c) Count Index after deleting rightmost leaf

Figure 6: Deleting a leaf that has no siblings

2. (Leaf has a sibling): In this case, we check whether the leaf (say cl) or its sibling (say cs)has a neighbor without any sibling of its own. If neither the leaf or its sibling have such aneighbor, then we delete the leaf node and update the value at its parent. Otherwise, let cn

denote the neighbor of the leaf (or its sibling) that has no sibling of its own. We delete cl andassign cn to be the sibling of cs.

(b) Count Index after deletion

1 3

4

7

3 3

6

3

3

(a) Deleting a leaf that has a sibling

Figure 7: Deleting a leaf that has a sibling

Consider a count index on a sequence with five run-lengths: 1,3, 3, 1 and 1 (shown in Figure 5). Wenote that although the count index appears to be unbalanced, its height is in fact ! "log2(#nodes =5)#. We show that this is always the case using Claim 2.3. Suppose we want to delete the rightmostcount from the count index shown in Figure 5. Since the leaf node corresponding to the rightmostcount (= 1) does not have a sibling (Case 1), we delete it and and all its ancestors which are shownas hatched nodes in Figure 6(a). The state of the count index after deleting its rightmost leaf is

7

Figure 5: Count Index on a sequence with five run-lengths: 1,3, 3, 1 and 1

1. (Leaf has no siblings): In this case, we delete the leaf and itsancestors. If the new root has only one child, we make itschild the new root node and iterate down the tree.

2. (Leaf has a sibling): In this case, we check whether the leaf(say cl) or its sibling (say cs) has a neighbor without anysibling of its own. If neither the leaf or its sibling have sucha neighbor, then we delete the leaf node and update the valueat its parent. Otherwise, let cn be the neighbor of the leaf (orits sibling) that has no sibling of its own. We delete cl andassign cn to be the new sibling of cs.

Consider a count index with five run-lengths: 1, 3, 3, 1 and 1(shown in Figure 5). We note that although the count index ap-pears to be unbalanced, its height is in fact O(log2(no. of nodes) =log 5). We show that this is always the case using Claim 2.3. Sup-pose we want to delete the rightmost count from the count indexshown in Figure 5. Since the leaf node corresponding to the right-most count (= 1) does not have a sibling (Case 1), we delete itand all of its ancestors which are shown as hatched nodes in Fig-ure 6(a). The state of the count index after deleting its rightmostleaf is shown in Figure 6(b). Suppose that we delete the rightmost

1

9

1

1

1 3

4

8

3 1

4

Figure 5: Count index on a sequence with five run-lengths: 1, 3, 3, 1 and 1

1. (Leaf has no siblings): In this case, we delete the leaf and its ancestors. If the new root hasonly one child, we make its child the new root node and iterate down the tree.

(b) Count Index after deletion

1 3

4

8

3

4

1

1

1

9

(a) Deleting a leaf that has no sibling

1 3

4

8

3 1

4

1 1 3

4

7

3

3

(c) Count Index after deleting rightmost leaf

Figure 6: Deleting a leaf that has no siblings

2. (Leaf has a sibling): In this case, we check whether the leaf (say cl) or its sibling (say cs)has a neighbor without any sibling of its own. If neither the leaf or its sibling have such aneighbor, then we delete the leaf node and update the value at its parent. Otherwise, let cn

denote the neighbor of the leaf (or its sibling) that has no sibling of its own. We delete cl andassign cn to be the sibling of cs.

(b) Count Index after deletion

1 3

4

7

3 3

6

3

3

(a) Deleting a leaf that has a sibling

Figure 7: Deleting a leaf that has a sibling

Consider a count index on a sequence with five run-lengths: 1,3, 3, 1 and 1 (shown in Figure 5). Wenote that although the count index appears to be unbalanced, its height is in fact ! "log2(#nodes =5)#. We show that this is always the case using Claim 2.3. Suppose we want to delete the rightmostcount from the count index shown in Figure 5. Since the leaf node corresponding to the rightmostcount (= 1) does not have a sibling (Case 1), we delete it and and all its ancestors which are shownas hatched nodes in Figure 6(a). The state of the count index after deleting its rightmost leaf is

7

1

9

1

1

1 3

4

8

3 1

4

Figure 5: Count index on a sequence with five run-lengths: 1, 3, 3, 1 and 1

1. (Leaf has no siblings): In this case, we delete the leaf and its ancestors. If the new root hasonly one child, we make its child the new root node and iterate down the tree.

(b) Count Index after deletion

1 3

4

8

3

4

1

1

1

9

(a) Deleting a leaf that has no sibling

1 3

4

8

3 1

4

1 1 3

4

7

3

3

(c) Count Index after deleting rightmost leaf

Figure 6: Deleting a leaf that has no siblings

2. (Leaf has a sibling): In this case, we check whether the leaf (say cl) or its sibling (say cs)has a neighbor without any sibling of its own. If neither the leaf or its sibling have such aneighbor, then we delete the leaf node and update the value at its parent. Otherwise, let cn

denote the neighbor of the leaf (or its sibling) that has no sibling of its own. We delete cl andassign cn to be the sibling of cs.

(b) Count Index after deletion

1 3

4

7

3 3

6

3

3

(a) Deleting a leaf that has a sibling

Figure 7: Deleting a leaf that has a sibling

Consider a count index on a sequence with five run-lengths: 1,3, 3, 1 and 1 (shown in Figure 5). Wenote that although the count index appears to be unbalanced, its height is in fact ! "log2(#nodes =5)#. We show that this is always the case using Claim 2.3. Suppose we want to delete the rightmostcount from the count index shown in Figure 5. Since the leaf node corresponding to the rightmostcount (= 1) does not have a sibling (Case 1), we delete it and and all its ancestors which are shownas hatched nodes in Figure 6(a). The state of the count index after deleting its rightmost leaf is

7

1

9

1

1

1 3

4

8

3 1

4

Figure 5: Count index on a sequence with five run-lengths: 1, 3, 3, 1 and 1

1. (Leaf has no siblings): In this case, we delete the leaf and its ancestors. If the new root hasonly one child, we make its child the new root node and iterate down the tree.

(b) Count Index after deletion

1 3

4

8

3

4

1

1

1

9

(a) Deleting a leaf that has no sibling

1 3

4

8

3 1

4

1 1 3

4

7

3

3

(c) Count Index after deleting rightmost leaf

Figure 6: Deleting a leaf that has no siblings

2. (Leaf has a sibling): In this case, we check whether the leaf (say cl) or its sibling (say cs)has a neighbor without any sibling of its own. If neither the leaf or its sibling have such aneighbor, then we delete the leaf node and update the value at its parent. Otherwise, let cn

denote the neighbor of the leaf (or its sibling) that has no sibling of its own. We delete cl andassign cn to be the sibling of cs.

(b) Count Index after deletion

1 3

4

7

3 3

6

3

3

(a) Deleting a leaf that has a sibling

Figure 7: Deleting a leaf that has a sibling

Consider a count index on a sequence with five run-lengths: 1,3, 3, 1 and 1 (shown in Figure 5). Wenote that although the count index appears to be unbalanced, its height is in fact ! "log2(#nodes =5)#. We show that this is always the case using Claim 2.3. Suppose we want to delete the rightmostcount from the count index shown in Figure 5. Since the leaf node corresponding to the rightmostcount (= 1) does not have a sibling (Case 1), we delete it and and all its ancestors which are shownas hatched nodes in Figure 6(a). The state of the count index after deleting its rightmost leaf is

7

Figure 6: Deleting a leaf that has no siblings

1

9

1

1

1 3

4

8

3 1

4

Figure 5: Count index on a sequence with five run-lengths: 1, 3, 3, 1 and 1

1. (Leaf has no siblings): In this case, we delete the leaf and its ancestors. If the new root hasonly one child, we make its child the new root node and iterate down the tree.

(b) Count Index after deletion

1 3

4

8

3

4

1

1

1

9

(a) Deleting a leaf that has no sibling

1 3

4

8

3 1

4

1 1 3

4

7

3

3

(c) Count Index after deleting rightmost leaf

Figure 6: Deleting a leaf that has no siblings

2. (Leaf has a sibling): In this case, we check whether the leaf (say cl) or its sibling (say cs)has a neighbor without any sibling of its own. If neither the leaf or its sibling have such aneighbor, then we delete the leaf node and update the value at its parent. Otherwise, let cn

denote the neighbor of the leaf (or its sibling) that has no sibling of its own. We delete cl andassign cn to be the sibling of cs.

(b) Count Index after deletion

1 3

4

7

3 3

6

3

3

(a) Deleting a leaf that has a sibling

Figure 7: Deleting a leaf that has a sibling

Consider a count index on a sequence with five run-lengths: 1,3, 3, 1 and 1 (shown in Figure 5). Wenote that although the count index appears to be unbalanced, its height is in fact ! "log2(#nodes =5)#. We show that this is always the case using Claim 2.3. Suppose we want to delete the rightmostcount from the count index shown in Figure 5. Since the leaf node corresponding to the rightmostcount (= 1) does not have a sibling (Case 1), we delete it and and all its ancestors which are shownas hatched nodes in Figure 6(a). The state of the count index after deleting its rightmost leaf is

7

Figure 7: Deleting a leaf that has a sibling

leaf again. Since the rightmost leaf has a sibling and no neighborswithout a sibling, we delete the leaf node and update the value ofits parent. The resulting count index is shown in Figure 6(c). Nowsuppose we delete the leftmost count (= 1). Since the leftmost leafhas a sibling (with a count of 3) and a neighbor without any siblings(Case 2), we delete the leftmost node and pair up the sibling withthe neighboring leaf. This procedure is shown in Figure 7(a) and(b). In Figure 7(a), the hatched nodes are deleted.

Claim 2.1. Deleting a leaf from a count index takes time that islinear in the height of the count index.

PROOF. Let f(k) and g(k) be the time taken to delete a node ata height of k using cases 1 and 2 respectively. Then the followingrecurrence relations hold.

f(k) ≤ 1 + maxf(k − 1), g(k − 1) (2)g(k) = f(k − 1) + 1 (3)

On solving for f(k) and g(k), we get f(k) = g(k) = c× k + dwhere c and d are constants. Therefore, a leaf can be deleted froma count index of height h in O(h) time.

Updating the Root: When we delete a leaf node which causesone of the root’s children to be deleted as well (an example is shownin Figure 6(a)), the root node of the count index has to be updated.As a general rule, after the deletion procedure terminates, we checkwhether the root of the count index has two children or not. If theroot has two children, no further update is required. However, ifthe root has only one child, we set its child to be the new root nodeand recurse down the count index.

Inserts: The process of inserting new leaves into a count indexis similar to the process of deleting leaves. Suppose we want to

insert a leaf node w between two leaves: u and v. There are twocases depending on whether u or v have siblings or not.

1. (One of u or v has no siblings): Without loss of generality,we can assume that u has no siblings. We make w the siblingof u and update the count of their parent.

2. (Both u and v have siblings): If u and v are siblings of eachother then we make w the sibling of u by updating the countat v. Next, we insert a leaf with the same count as v at theleaf level and set its parent to have the same count as itself.

Claim 2.2. Inserting a leaf into a count index takes time that islinear in the height of the count index.

PROOF. Let f(k) and g(k) be the time taken to insert a node ata height of k using cases 1 and 2 respectively. Then, the followingrecurrence relations hold.

f(k) = f(k − 1) + 1 (4)g(k) ≤ 1 + maxf(k − 1), g(k − 1) (5)

On solving for f(k) and g(k), we get f(k) = g(k) = c× k + dwhere c and d are constants. Therefore, a leaf can be inserted intoa count index of height h in O(h) time.

Balancing Count Indexes: Using Claims 2.1 and 2.2, we haveestablished that the node insertions and deletions in a count indexof height h take O(h) time. We still need to show that an updatedcount index is balanced i.e. h = O(log n). Count indexes can bepotentially unbalanced due to nodes which are not paired up withtheir neighbors. We call such unpaired nodes as holes. Since a nodein a count index stores the sum of its children’s counts, we cannotuse traditional tree rotation techniques for tree balancing as is usedin AVL Trees [2] and Red-Black Trees [12].

Balancing Count Indexes: Using Claims 2.1 and 2.2, we have established that node insertionsand deletions in a count index of height h take O(h) time. We still need to show that an updatedcount index is balanced i.e. h = O(log n). Count indexes can be potentially unbalanced due tonodes which are not paired up with their neighbors. We call such unpaired nodes as holes. Sincea node in a count index stores the sum of the children’s counts, we cannot use traditional treerotation techniques for tree balancing as is used in Red Black Trees [12] and AVL Trees [2].

Consider a count index with n leaf nodes. The maximum number of holes at the leaf level ofthe count index is !n

2 ". When we insert or delete a node from the count index, we propagate holeson to higher levels where they either pair up with an existing hole or cause a node to be split (whileinserting a node) or two nodes to be merged (while deleting a node). The count index shown in

7

1

1

1

3 3

6

3 3

6

Figure 8: Inserting counts at a ‘hole’ position

Figure 7(b) has two hole positions at the leaf level (shown in Figure 8). When we insert a count(say 1) into either of these holes, the hole propagates to the next level and pairs up with the nodewhich was previously the root. The final state of the count index is shown in Figure 9.

7

1

1

1

3 3

6

3 3

6

Figure 9: State of the count index after insertion

Claim 2.3. The height of a count index with n leaves is O(log n) i.e. the count index is alwaysbalanced.

Proof. Suppose that there are n nodes paired up at the leaf level in a count index. The maximumnumber of holes at leaf level is #n

2 $. At subsequent levels, the maximum number of holes is #n4 $,

#n8 $, # n

16$ and so on. Hence, at every level of the count index, at most one-third of the nodes canpotentially be holes. The height of the count index index is thus log (3 % n

2 ) = O(log n).

We can, therefore, update a count index in time that is logarithmic in the number of runs in asequence. In the remainder of the section we show that we can actually do better if we are insertinga sequence of runs into the input sequence.

Bulk inserting sequences: Consider a count index with n leaf nodes. Suppose that we wouldlike to insert a sequence of k runs. Naively, we could insert the k runs using the insert proceduredescribed above in O(k% log (n+ k)) time. However, we could do better if we made use of the factthat the k runs are adjacent. We present below a procedure that e!ciently inserts a sequence of kruns (represented as [ci]) into a count index T with n leaves.

9

Figure 8: Inserting counts at a ‘hole’ position

Consider a count index with n leaf nodes. The maximum num-ber of holes at the leaf level of the count index is dn

2e. When we

insert or delete a node from the count index, we propagate the holesto higher levels where they either pair up with an existing hole orcause a node to be split (while inserting a node) or cause two nodesto be merged (while deleting a node). The count index shown inFigure 7(b) has two hole positions at the leaf level (shown in Fig-ure 8). When we insert a count (say 1) into either of these holes, thehole propagates to the next level and pairs up with the node whichwas previously the root. The final state of the count index is shownin Figure 9.

Claim 2.3. The height of a count index is logarithmic in the num-ber of its leaves. i.e. the count index is always balanced.

PROOF. Suppose that there are N nodes that are paired up insome level of a count index. There can be a hole adjacent to eachpair. The maximum number of holes in each level is dN

2e. In every

level of a count index at most one-third of the nodes can potentiallybe holes and at least two-third of the nodes are paired up. Hence,the height of a count index with n leaf nodes is at most log ( 3

2) ×

log n = O(log n).

Balancing Count Indexes: Using Claims 2.1 and 2.2, we have established that node insertionsand deletions in a count index of height h take O(h) time. We still need to show that an updatedcount index is balanced i.e. h = O(log n). Count indexes can be potentially unbalanced due tonodes which are not paired up with their neighbors. We call such unpaired nodes as holes. Sincea node in a count index stores the sum of the children’s counts, we cannot use traditional treerotation techniques for tree balancing as is used in Red Black Trees [12] and AVL Trees [2].

Consider a count index with n leaf nodes. The maximum number of holes at the leaf level ofthe count index is !n

2 ". When we insert or delete a node from the count index, we propagate holeson to higher levels where they either pair up with an existing hole or cause a node to be split (whileinserting a node) or two nodes to be merged (while deleting a node). The count index shown in

7

1

1

1

3 3

6

3 3

6

Figure 8: Inserting counts at a ‘hole’ position

Figure 7(b) has two hole positions at the leaf level (shown in Figure 8). When we insert a count(say 1) into either of these holes, the hole propagates to the next level and pairs up with the nodewhich was previously the root. The final state of the count index is shown in Figure 9.

7

1

1

1

3 3

6

3 3

6

Figure 9: State of the count index after insertion

Claim 2.3. The height of a count index with n leaves is O(log n) i.e. the count index is alwaysbalanced.

Proof. Suppose that there are n nodes paired up at the leaf level in a count index. The maximumnumber of holes at leaf level is #n

2 $. At subsequent levels, the maximum number of holes is #n4 $,

#n8 $, # n

16$ and so on. Hence, at every level of the count index, at most one-third of the nodes canpotentially be holes. The height of the count index index is thus log (3 % n

2 ) = O(log n).

We can, therefore, update a count index in time that is logarithmic in the number of runs in asequence. In the remainder of the section we show that we can actually do better if we are insertinga sequence of runs into the input sequence.

Bulk inserting sequences: Consider a count index with n leaf nodes. Suppose that we wouldlike to insert a sequence of k runs. Naively, we could insert the k runs using the insert proceduredescribed above in O(k% log (n+ k)) time. However, we could do better if we made use of the factthat the k runs are adjacent. We present below a procedure that e!ciently inserts a sequence of kruns (represented as [ci]) into a count index T with n leaves.

9

Figure 9: State of the count index after inserting

Therefore, we can incrementally maintain a run-length encodedsequence using a count index in time that is logarithmic in the num-ber of the runs in the sequence.

Bulk Inserting Sequences: Consider a count index with n leafnodes. Suppose that we would like to insert a sequence of k runs.Naively, we could insert the k runs using the insert procedure inO(k × log (n + k)) time. However, we could do better if we madeuse of the fact that the k runs are adjacent. We present below aprocedure that efficiently inserts a sequence of k runs (dcie) into acount index T with n leaves.

• We construct a count index T ′ on the sequence of k runsdcie.

• We merge T and T ′. (Figure 10)

– Let u and v be the leaves in T between which the se-quence dcie is inserted.

– If u and v are siblings, we split them up convertingthem into holes.

– We pair up the left-most leaf of T ′ with u if both nodesare holes. Similarly we pair up the right-most leaf ofT ′ with v if both nodes are holes.

– We insert the rest of the leaves of T ′ into T withoutfurther changes and iterate at the next higher level of Tand T ′.

• At a height of log k, we insert the root of T ′ into T .

Time Complexity of Bulk Inserts: The construction of T ′ whichis a count index on k runs takes O(k) time. To insert the root of T ′

into T at a height of log k, we require O(log nk

) time. Let us denotethe time taken to merge two count indexes with n and k leaves asf(n, k). The bulk insert procedure results in the following recur-rence relations.

f(n, k) = f(n

2,k

2) + O (k) (6)

f(n, 1) = O (log n) (7)

On solving for f(n, k) we get f(n, k) = O (k + log n). Thususing the above procedure, we can amortize the cost of inserting asequence of runs in time that is almost linear in the number of theinserted runs.

2.4 Optimality of Incremental Maintenance us-ing Count Indexes

We have shown in Sections 2.2 and 2.3 that count indexes sup-port O(log n) offset-based look ups and in-place inserts, deletes andupdates of runs into a run-length encoded sequence with n runs. Wenow use a lower bound result on the complexity of incrementallymaintaining partial sums which has been proved in [8, 9, 19] toshow that the problem of incrementally maintaining a run-lengthencoded sequence with n runs requires Ω(log n) time . Given an

r’

T’

u’ v’

r’

k vertices

T

n vertices

u’u vv’

T U T’

n + k vertices

Merge

O(k + log n)

vu

Figure 10: Bulk inserting a sequence of runs into a count index

• We construct a count index T ! on the sequence [ci].

• We merge T and T !. (Figure 10)

– Let u and v be the leaves in T between which the sequence [ci] is inserted. Either of uor v could be null.

– If u and v are siblings, split u and v converting them into holes.

– We pair up the left-most leaf in T ! and u if both nodes are holes. Similarly, we pair upthe right-most leaf of T ! and v if both nodes are holes..

– We insert the rest of the leaves of T ! into T without further modifications.

– We iterate at the next higher level of T ! and T .

• At a height of log k, we insert the root of T ! into T .

Time Complexity of Bulk Inserts: The construction of T ! which is a count index on kruns takes O(k) time. To inserting the root of T ! into T at a height of log k we require O(log n

k )time. Let us denote the time taken to merge two count indexes with n and k leaves as the functionf(n, k). The procedure described above results in the following recurrence relations.

f(n, k) = f(n

2,k

2) + O(k) (6)

f(n, 1) = O(log n) (7)

On solving for f(n, k) we get, f(n, k) = O(k + log n). Thus using the above procedure, we caninsert a sequence of k runs in time that is almost linear in k.

2.4 Optimality of Incremental Maintenance using Count Indexes

We have shown in Sections 2.2 and 2.3 that we can leverage count indexes to support O(log n) o!set-based look ups and in-place inserts, deletes and updates of runs into a run-length encoded sequencewith n runs. We now use a lower bound result on the complexity of incrementally maintaining partialsums which has been proved in [8, 9, 19] to show that the problem of incrementally maintaininga run-length encoded sequence with n runs requires "(log n) time. Given an array a[i] and aparameter k, the partial sums problem computes

!ki=0 a[i] subject to updates of the form a[i] =

10

Figure 10: Bulk Inserting a sequence of runs into a count index

array of numbers a[i] and a parameter k, the partial sums prob-lem computes

∑ki=0 a[i] subject to updates of the form a[i] += x,

where x is a number. [8, 9, 19] have independently established thatincrementally maintaining partial sums while supporting in-placeupdates requires Ω(log n) time.

The problem of incrementally maintaining partial sums over anarray a[i] of length n can be reduced to the problem of incre-mentally maintaining run-length encoded sequences. We create arun-length encoded sequence with n runs. Every i corresponds to arun and the run-length of the ith run is equal to a[i]. An update a[i]+= x to the partial sums problem is equivalent to incrementing therun-legth of the run at the offset

∑ij=0 a[i] by x in the run-length

encoded sequence. The computation of the partial sum at a[k] isequivalent to the computation of the starting offset of the i + 1th

run. Therefore, incrementally maintaining a run-length encodedsequence with n runs requires Ω(log n) time. In fact, the prob-lem of incrementally maintaining run-length encoded sequences ismore general than the problem of incrementally maintaining partialsums because the partial sums problem does not support in-placeinsertion or deletion of array elements. Thus, leveraging count in-dexes to incrementally maintain a run-length encoded sequence isoptimal.

3. EXTENSIONSIn the previous section we showed that count indexes can effi-

ciently look up and update a run-length encoded sequence with nruns in O(log n) time. Bitmap encoding is another compressiontechnique that is used in column stores to compress the attributeswith a few distinct values. Bitmaps are typically sparse and are fur-ther compressed using run-length encoding. In this section, we ex-tend count indexes to efficiently update bitmap encoded sequences.We also discuss how count indexes can be adapted to block-basedstores where the number of I/Os determine the time complexity ofupdates.

Updating Bitmap Encoded Sequences: Bitmap encoding a se-quence creates a bit-vector for every distinct value in the sequence.If the sequence contains the value v at the ith position, then thebit-vector corresponding to the value v contains the bit 1 at the ith

position. Bitmaps are typically sparse and are run-length encoded.When new values are added to the sequence, additional bits are ap-pended to the end of a bitmap. When values are deleted from abitmap, the corresponding bits are not deleted. Instead, the deletedvalues are tombstoned (see [10] for details). The insertion of anew value or the deletion of an existing value at a given offset in abitmap takes time that is linear in the size of the bitmap. We can

a[i]+x. [8, 9, 19] have independently established that incrementally maintaining partial sums whilesupporting in-place updates requires !(log n) time.

The problem of incrementally maintaining partial sums problem over an array a[i] of lengthn can be reduced to the problem of incrementally maintaining run-length encoded sequences bycreating a run-length encoded sequence with n runs. Every i corresponds to a run and the run-length of ith run is equal to a[i]. An update a[i] = a[i]+x to the partial sums problem is equivalentto the insertion of x runs at the o"set

!ij=0 a[i] in the run-length sequence. The computation of the

partial sum at a[k],!k

i=0 a[i] is equivalent to the computation of the starting o"set of the i + 1th

run. Therefore incrementally maintaining a run-length encoded sequence with n runs requires!(log n) time. In fact, the problem of incrementally maintaining run-length encoded sequencesis more general than the problem of incrementally maintaining partial sums because the partialsums problem does not support in-place insertion or deletion of new array elements. By leveragingcount indexes, we can support o"set-based look ups and in-place inserts, deletes and updates in arun-length encoded sequence with n runs in O(log n) time which is optimal.

3 Extensions

In the previous section we showed that count indexes can e#ciently look up and update a run-length sequence with n runs in O(log n) time. Bitmap encoding is another compression techniquethat is used in columnar databases to compress columns with a few distinct values. Bitmaps aretypically sparse and are further compressed using run-length encoding. In this section, we extendcount indexes to e#ciently update bitmap encoded sequences as well. Finally, we discuss how countindexes could be generalized to block oriented stores where the number of I/Os determine the timecomplexity of updates.

Count Index over Bitmap a

2

2

3

3

a

b

a

b

Bitmap a Bitmap b

bitmapRun!length encodedRun!length encoded

sequence

2 3 3 2

5 5

10

2 3 3 2

5 5

10

1

0

0

1

2

2

3

3

0

1

1

0

2

2

3

3

1 0 01 1 10 0

Count Index over Bitmap b

Figure 11: Count Indexes on Run-length Encoded Bitmaps

Updating Bitmap Encoded Sequences: Bitmap encoding a sequence creates a bit-vectorfor every distinct value in the sequence. If the sequence contains the value v at the ith position,then the bit-vector corresponding to the value v contains the bit 1 at the ith position. Bitmaps aresparse and are compressed using run-length encoding. When new values are added to the sequence,additional bits are appended to the end of the bitmaps. When values are deleted from a bitmap, the

11

Figure 11: Count Indexes on Run-length Encoded Bitmaps

significantly improve the update complexity by extending count in-dexes to operate on bitmap encoded sequences. For every distinctvalue in an input sequence, we create a count index on the corre-sponding run-length encoded bitmap. The bitmaps can be lookedup and updated at a given offset in time that is logarithmic in thenumber of runs in the bitmap. We present an example to show howcount indexes can be extended to operate on bitmapped sequences.

Example 3.1. Suppose we bitmap encode the sequence as given inExample 1.1. we get two bitmaps [1 1 0 0 0 1 1 1 0 0] for the value‘a’ and [0 0 1 1 1 0 0 0 1 1] for ‘b’. Run-length encoding thesebitmaps would produce the sequences: [(1, 2), (0, 3), (1, 3), (0, 2)]and [(0, 2), (1, 3), (0, 3), (1, 2)] respectively. Two count indexesare constructed on the resulting sequences. These indexes (shownin Figure 11) are identical to each other.

In general, if an input sequence has n runs and k distinct values,then we could look up and update the bitmap encoded sequenceusing count indexes in time that is proportional to k × log n

kin

the worst case. However, we can independently execute the lookup and update algorithms over each of the k bitmaps in parallel inO(log n) time.

Adapting Count Indexes to Block-Based Stores: In Section 2,we stored a single run count in each leaf node of a count index andthe sum of two child nodes in their parent. In order to adapt countindexes to block-based stores where each block of data is a diskpage instead of a single value, we modify count indexes to store

Figure 12: Incremental Maintenance of Count Indexes in Block-based StoresFigure 12: Incremental Maintenance of Count Indexes adapted to Block-oriented Stores

(a)

Insert(Node N , Count C, Value V )if N is not full then

Insert !V,C" into NUpdate the sum of the counts of N and its ancestors

elseCreate a new node MMove !V,C" and half of the values or pointers andthe counts present in N over to MUpdate the sum of the counts of N and MP # parent of NC ! # Sum of the counts of MInsert(P , C !, M )

end ifIn order to adapt count indexes to block-oriented stores, we establish a new

index invariant: Every non-root node of a count index is at least half-full. We canextend count indexes to disk by increasing the fan-out of every node in a countindex much like B+ trees [?]. We call this index structure as a count+ index. Weassign the size of a node of the count+ index to be equal to the size of a page ondisk. If the size of a page on disk is S bytes and every value in the sequence isW bytes long, then the maximum number (say k) of counts that can be stored atan interior node and a leaf node of a count+ index is given by

!S"412 and

!S"4W+4

respectively. Every interior node maintains the sum of its children’s counts as wellas the pointers to its children. Every node except for the root must have at least[k2 ] counts. The algorithms to update a count+ index when counts are inserted

or deleted are identical to the respective algorithms for count indexes with thefollowing exceptions:

1. When we insert a value or a count to a node of a count+ index that is full i.e.has k counts, we create a new node and move half of the counts / values tothe newly created node.

2. When we delete a value or a count from a non-root node of the count+ indexindex that has exactly [k

2 ] counts, two possible cases arise:

(a) There is a neighboring node which has at least [k2 ] + 1 counts. In thiscase, the node is updated by moving either the rightmost count (if theneighbor is on the left) or the leftmost count (if the neighbor is on theright) from the neighboring node.

(b) All the neighboring nodes have [k2 ] counts. In this case we can select

any of the neighbors and merge the counts of the node and its neighborand update the sum of the resulting node.

16

(b)

Delete(Node N , Count C, Value V )if N is exactly half-filled then

Delete !V,C" into Nif all neighbors of N are half-filled then

Merge a neighbor of N say M with NP # parent of MSuppose C ! # Sum of counts of MDelete(P , C !, M )

elseM is a neighbor of N which is more than half-filledLet Q be a pointer contained in M which is closestto NLet the sum of counts of Q be C !

Delete(M , C !, Q)Insert(N , C !, Q)

end ifUpdate the sum of the counts of N and its ancestors

elseDelete !V,C" from NUpdate the sum of the counts of N and its ancestors

end ifIn order to adapt count indexes to block-oriented stores, we establish a new

index invariant: Every non-root node of a count index is at least half-full. We canextend count indexes to disk by increasing the fan-out of every node in a countindex much like B+ trees [?]. We call this index structure as a count+ index. Weassign the size of a node of the count+ index to be equal to the size of a page ondisk. If the size of a page on disk is S bytes and every value in the sequence isW bytes long, then the maximum number (say k) of counts that can be stored atan interior node and a leaf node of a count+ index is given by

!S"412 and

!S"4W+4

respectively. Every interior node maintains the sum of its children’s counts as wellas the pointers to its children. Every node except for the root must have at least[k2 ] counts. The algorithms to update a count+ index when counts are inserted

or deleted are identical to the respective algorithms for count indexes with thefollowing exceptions:

1. When we insert a value or a count to a node of a count+ index that is full i.e.has k counts, we create a new node and move half of the counts / values tothe newly created node.

2. When we delete a value or a count from a non-root node of the count+ index

16

a di!erential store. PDTs record the deltas of the o!sets of the updated tuples within a segment.The idea of operating on deltas of o!sets is common to both PDTs and count indexes. Howeverthere are di!erences that separate the two data structures. Count indexes are designed to operateon a single store (one that contains the compressed representations of tuples only) while supportinge"cient reads and updates. On the other hand, a PDT visualizes a database as a two-pronged store:a read-optimized store and a write-optimized store (one that contains uncompressed representationof tuples). Second, count indexes are more space e"cient than PDTs. If k values are inserted intoand later deleted from a sequence of n values, the space required to store the corresponding PDTwould be O(n + k), whereas a count index would require only O(n) space. Futher, a PDT requiresa merge-scan to to bulk insert values or runs of values. Therefore the time complexity of updatinga relation is O(n) where n is the number of tuples (or pages on disk). A count index on the otherhand requires O(k! log n) time in the worst case to insert k runs. If the number of updated tuplesis a small fraction of the total number of tuples (i.e. k " n), O(k! log n) updates are much betterthan O(n) updates. If the k runs are contiguous, then they can be inserted into a count indexin O(k + log n) time which is almost linear in the number of updated tuples. Additionally, whileapplying updates using PDTs the columns are decompressed and later re-compressed, which canbe expensive. In contrast, count indexes operate directly on the compressed sequences of valuesand can thus be incrementally maintained without decompressing the sequence.

Incremental Maintenance of aggregates: Prior work [4, 6, 8, 9, 11, 14, 18, 19, 21, 22] onspatio-temporal aggregation for range queries have studied the problem of e"ciently computingthe partial sums

!ki=0 a[i] for an array a[i] subject to the updates of the form a[i] = a[i] + x. As

shown in Section 2.4, the problem of incrementally maintaining partial sums is closely related tothe problem of incrementally maintaining run-lenth encoded sequences. However, the data struc-tures [8, 9, 11, 14, 18, 19, 21, 22] that have been proposed for incremental maintaining partial sums

13

multiple counts in each node.Suppose each disk page is S Bytes long and the width of the

attribute to be stored is W Bytes long. We assume that the run-lengths can be represented as 4 Byte integers. In each leaf node ofour modified count index, we store a maximum of Nl attribute val-ues, their respective counts and the sum of their Nl counts whereNl = S−4

W+4. In each interior node, we now store a maximum of

Ni pointers (8 Bytes long) to its children and the sum of their re-spective counts (4 Bytes each) where Ni = S−4

W+12. To adapt count

indexes to block-oriented stores, we also establish a new index in-variant: every non-root node is at least half-full i.e. every leaf nodestores at least dNl

2e attribute values and counts and every interior

nodes stores at least dNi2e pointers to its children.

The modified algorithms for inserting and deleting a run are pre-sented in Figures 12(a) and (b) respectively.

4. RELATED WORKThe problem of efficiently updating compressed columns has ben

well-studied in the database community in the context of optimiz-ing column store updates. While column stores such as [16] supportappend-only inserts, others such as [3, 13, 15, 20] merge differ-ential updates from a write-optimized store into a read-optimizedstore. An append-only insert scheme such as [16] is easy to imple-ment. However such a scheme could arbitrarily degrade the com-pression achieved on the non-sort key columns by order-sensitiveschemes such as run-length encoding or bitmap encoding [17] andthus lead to inefficient look ups.

Column stores such as [3, 13, 15, 20] maintain a differential storein addition to a read-optimized store. The updates are buffered inthe differential store and are later merged with the read-store. Thistechnique amortizes the cost of updates by applying the updates inbatches. Recently, [13] has proposed a data structure called Posi-tional Delta Trees (PDTs) which efficiently buffer updates in sucha differential store. PDTs record the deltas of the offsets of theupdated tuples within a segment. The idea of operating on deltasof offsets is common to both PDTs and count indexes. Howeverthere are differences that separate the two. Count indexes are de-signed to operate on a single store only (one which contains thecompressed representations of the tuples) while supporting efficientreads and updates. On the other hand, a PDT visualizes a database

as a two-pronged store: a read-optimize store and a write-optimizedstore (one which contains the uncompressed representation of thetuples). Second, count indexes are more space efficient than PDTs.If k values are inserted into and later deleted from a sequence ofn values, the space required to store the corresponding PDT wouldbe O(n+k), whereas a count index would require only O(n) space.Further, a PDT requires a merge scan to bulk insert values or runsof values. Therefore the time complexity of updating a relation isO(n) where n is the total number of tuples. On the other hand, acount index requires O(k× log n) time in the worst case to insert kruns. If the number of updated tuples is a small fraction of the totalnumber of tuples (k n), O(k×log n) time updates are much bet-ter than O(n) updates. If the k runs are adjacent, then they can beinserted into a count indexed in O(k + log n) time which is almostlinear in the number of updated tuples. Additionally, while apply-ing updates using PDTs the columns are decompressed and laterre-compressed, which can be expensive. In contrast, count indexesoperate directly on the compressed sequences of values and can beincrementally maintained without decompressing the sequence.

Incremental maintenance of aggregates: Prior work [4, 6, 8,9, 11, 14, 18, 19, 21, 22] on spatio-temporal aggregation for rangequeries have studied the problem of efficiently computing the par-tial sums

∑ki=0 a[i] for an array a[i] subject to the updates of

the form a[i] += x. As shown in Section 2.4, the problem of incre-mentally maintaining partial sums is closely related to the problemof incrementally maintaining run-length encoded sequences. How-ever, the data structures [8, 9, 11, 14, 18, 19, 21, 22] that have beenproposed for problem of incrementally maintaining partial sumsare not dynamic. For instance, the insertions and the deletions ofvalues in the array are not supported on proposed data structures.These operations are equivalent of supporting in-place insertionand deletion of runs in a run-length encoded sequence. There isanother distinction between incrementally maintaining run-lengthencoded sequences and the problem of efficiently computing ag-gregates over spatial and temporal data. Consider a set of points inthe 2-D plane which is shown in Figure 13. Suppose we are inter-ested in efficiently computing the sum of the weights of the pointswithin a given bounding box, say [2, 1]× [4, 5]. To efficiently com-pute the sum of the weights we can leverage previously proposeddata structures such as Orthogonal Range Trees and k-D Trees [6].

value updates in column store relations. In addition, count indexes can bulk insert a sequence ofvalues in time that is almost linear in the number of inserted runs, thus improving the amortizedcost of batch updates.

To conclude, we summarize the performance of count indexes on di!erent compression schemesin Table 2.

Table 1: Performance of count indexes on various encoding schemesN = number of values and n = number of runs

Encoding Scheme create look-up update bulk insert (k contiguous runs)Run-length Encoding O(n) O(log n) O(log n) O(k+log n)

Bitmap Encoding (parallel operations) O(n) O(log n) O(log n) O(k+log n)Uncompressed O(N + n) O(log n) O(log n) O(k+log n)

Table 2: Performance of count indexes on various encoding schemesN = number of values and n = number of runs

Encoding Scheme create look-up update bulk insert (k contiguous runs)Run-length Encoding O(n) O(log n) O(log n) O(k+log n)

Bitmap Encoding (parallel operations) O(n) O(log n) O(log n) O(k+log n)

gle store (one that contains the compressed representationsof tuples only) while supporting e!cient reads and updates.On the other hand, a PDT visualizes a database as a two-pronged store: a read-optimized store and a write-optimizedstore (one that contains uncompressed representation of tu-ples). Second, count indexes are more space e!cient thanPDTs. If k values is inserted into and later deleted from asequence of n values, the space required to store the corre-sponding PDT would be O(n + k), whereas a count indexwould require only O(n) space. Futher, a PDT requires amerge-scan to to bulk insert values or runs of values. There-fore the time complexity of updating the database is O(n)where n is the number of tuples (or pages on disk). A countindex on the other hand requires O(k ! log n) time in theworst case to insert k runs. If the k runs are contiguous,they can be inserted into the count index in O(k + log n)time. Additionally, while applying updates using PDTs thecolumns are decompressed and later re-compressed, whichcan be expensive. In contrast, count indexes operate oncompressed sequences of values and can be incrementallymaintained without decompressing the sequence.

There has been prior work (e.g. [?]) to e!ciently updatecumulative frequencies. [?] has proposed a data structurecalled Fenwick Trees that supports O(log n) time look upsand in-place updates of the frequencies. However, unlikecount indexes, Fenwick trees cannot support sub-linear in-serts or deletes of frequencies. In fact, when we insert a newfrequency or delete an existing frequency, the Fenwick treehas to be created from scratch. Count index is the first in-dex structure that supports O(log n) o"set based updatesand look ups on an O(n) sized run-length encoded or bitmapencoded sequence.

5. CONCLUSION AND FUTURE WORKIn this paper, we have proposed a novel indexing schemecalled count indexes that supports o"set-based look ups andupdates on a run-length encoded sequence with n runs inO(log n) time. Since columnar databases compress attributevalues using run length encoding, count indexes can be po-tentially used as an auxiliary data structure to e!cientlysupport single value updates. In addition, count indexescan bulk insert a sequence of values in time that is almostlinear in the number of inserted runs, thus amortizing thetime to insert values in bulk.

We have generalized count indexes to operate on bitmap en-

coded sequences as well as uncompressed sequences. Countindexes significantly reduce the time complexity of o"set-based updates on run-length encoded columns from O(n) toO(log n). The problem of whether the time complexity canbe lowered further is open.

To conclude, we summarize the performance of count in-dexes in Table ??.

References

[1] D. J. Abadi, P. A. Boncz, and S. Harizopoulos. Column oriented database systems. PVLDB,2009.

[2] G. M. Adelson-Velskii and Y. M. Landis. An algorithm for the organization of information.Soviet Mathematics Doklady, 1962.

[3] P. Boncz. Monet: A next-generation dbms kernel for query-intensive applications. Ph.D.Thesis, Universiteit van Amsterdam, 2002.

[4] B. Chazelle and B. Rosenberg. Computing partial sums in multidimensional arrays. In Pro-ceedings of the fifth annual symposium on Computational Geometry, 1989.

[5] G. Copeland and S. Khoshafian. A decomposition storage model. In SIGMOD, 1985.

[6] T. H. Cormen, C. E. Leiserson, R. L. Rivest, and C. Stein. Introduction to Algorithms. 2001.

[7] P. M. Fenwick. A new data structure for cumulative frequency tables. Software: Practice andExperience, 1994.

[8] M. L. Fredman. A lower bound on the complexity of orthogonal range queries. J. ACM, 1981.

[9] M. L. Fredman. The complexity of maintaining an array and computing its partial sums. J.ACM, 1982.

[10] H. Garcia-Molina, J. D. Ullman, and J. Widom. Database Systems: The Complete Book. 2008.

[11] S. Govindarajan, P. K. Agarwal, and L. Arge. Crb-tree: An e"cient indexing scheme forrange-aggregate queries. In ICDT, 2003.

[12] L. J. Guibas and R. Sedgewick. A dichromatic framework for balanced trees. 1978.

[13] S. Heman, M. Zukowski, N. J. Nes, L. Sidirourgos, and P. Boncz. Positional update handlingin column stores. In SIGMOD, 2010.

[14] C. Ho, R. Agrawal, N. Megiddo, and R. Srikant. Range queries in olap data cubes. SIGMOD,1997.

15

are not dynamic. For instance, the insertions and the deletions of values between a[i] and a[i + 1]are not supported on these data structures. These operations are equivalent to supporting in-placeinsertions and deletions of runs in a run-length encoded sequence. There is another distinctionbetween incrementally maintaining run-length encoded columns and the problem of e!cently com-puting aggregates over spatial and temporal data. Consider a set of points in the 2-D plane whichis shown in Figure 13. Suppose we are interested in e!ciently computing the sum of the weights

sum (Bounding Box) = 25

5

1

11

3

7

45

1

6

Figure 13: Aggregation of weights of points on a 2-D plane

of points within a given bounding box, say [2, 1]! [4, 5]. To e!ciently compute the sum of weightsof the points within the bounding box we could use previously proposed data structures such asorthogonal range trees and k-D trees [6]. When we insert a new point say (3, 2) into our point set,the value of the other points is not a"ected. This is because there is an implicit ordering of pointsin a 2-D plane based on their x and y coordinates which are monotonically increasing. However, ifwe choose a di"erent ordering of the points such as the lexicographic rank of a point in the pointset, the insertion of a new point into the point set a"ects the rank of other points.The tuples ina column store are typically ordered lexicographically using sort-keys and the o"set of a tuple isgiven by the lexicographic rank of the sort key value for that tuple. This introduces a linear timecomplexity for the in-place insertion and deletion of tuples.

There has also been prior work (e.g. [7]) on e!ciently updating cumulative frequencies. [7] hasproposed a data structure called Fenwick Trees that supports O(log n) time look ups and in-placeupdates of the frequencies. However, unlike count indexes, Fenwick trees are reconstructed if anynew frequencies are inserted or if any existing frequencies are deleted. Count index is the first indexstructure that supports O(log n) in-place inserts, deletes and updates of runs and o"set-based lookups on an O(n) sized run-length encoded or bitmap encoded sequence.

5 Conclusion and Future Work

In this paper, we have proposed a novel indexing scheme called count indexes that supports o"set-based look ups and in-place inserts, deletes and updates in a run-length encoded sequence. Countindexes significantly reduce the time complexity of o"set-based updates on run-length encodedcolumns from O(n) to O(log n). We have generalized count indexes to incrementally maintainbitmap encoded sequences and adapted them to block oriented stores. We have also showed thatthe lower bound for incrementally maintaining run-length attributes is #(log n). Therefore ourtechnique of incrementally maintaining run-length attributes using count indexes is optimal.

Column stores compress attribute values using run length encoding and bitmap encoding. Hencecount indexes can be potentially leveraged as an auxiliary data structure to e!ciently support single

14

Figure 13: Aggregation of weights of points on a 2-D plane

When we insert a new point say (3, 2) into our point set, the valueof the other points is not affected. This is because there is an im-plicit ordering of the points in a 2-D plane based on their x and ycoordinates which are monotonically increasing. However, if wechoose a different ordering of the points such as the lexicographicrank of a point in the point set, the insertion of a new point affectsthe rank of other points. The tuples in a column store are typicallyordered lexicographically using sort-keys and the offset of a tuple isgiven by the lexicographic rank of the sort-key value for that tuple.This introduces a linear time complexity for the in-place insertionand deletion of the tuples.

There has also been prior work (e.g. [7]) on efficiently updatingcumulative frequencies. [7] has proposed a data structure calledFenwick Trees that supports O(log n) time look ups and in-placeupdates of the frequencies. However, unlike count indexes, Fen-wick trees have to be reconstructed if any new frequencies are in-serted or if any existing frequencies are deleted. Count index is thefirst data structure that supports O(log n) in-place inserts, deletesand updates of run and off-set based look ups on an O(n) sizedrun-length encoded or bitmap encoded sequence.

5. CONCLUSIONIn this paper, we have proposed a novel indexing scheme called

count indexes that supports efficient offset-based look ups and in-place inserts, deletes and updates of runs in a run-length encodedsequence. Count indexes significantly reduce the time complexityof updating values at supplied offsets in a run-length encoded se-quence with n runs from O(n) to O(log n). We have also shownthat the lower bound for incrementally maintaining run-length en-coded sequences with n runs is Ω(log n). Therefore our tech-nique of incrementally maintaining run-length encoded sequencesusing count indexes is optimal. We have also generalized countindexes to incrementally maintain bitmap encoded sequences andhave adapted count indexes to block-based stores.

Column stores compress the attribute values using run-length en-coding and bitmap encoding. Hence count indexes can be poten-tially leveraged as an auxiliary data structure to efficiently supportsingle value updates in column stores relations. In addition, countindexes can bulk insert a sequence of tuples in time that is almostconstant per inserted tuple. This lowers the time complexity of up-dating a batch of tuples from being linear in the total number oftuples using previous techniques such as [3, 13, 15, 20] to be linearin the number of updated tuples.

To conclude, we summarize the performance of count indexeson different compression schemes in Table 2.

6. REFERENCES[1] D. J. Abadi, P. A. Boncz, and S. Harizopoulos.

Column-oriented database systems. PVLDB, 2009.[2] G. M. Adelson-Velskii and E. M. Landis. An algorithm for

the organization of information. Soviet MathematicsDoklady, 1962.

[3] P. A. Boncz. Monet: A Next-Generation DBMS Kernel ForQuery-Intensive Applications. Ph.d. thesis, Universiteit vanAmsterdam, 2002.

[4] B. Chazelle and B. Rosenberg. Computing partial sums inmultidimensional arrays. In Proceedings of the fifth annualsymposium on Computational Geometry, 1989.

[5] G. P. Copeland and S. N. Khoshafian. A decompositionstorage model. SIGMOD, 1985.

[6] T. H. Cormen, C. Stein, R. L. Rivest, and C. E. Leiserson.Introduction to Algorithms. 2001.

[7] P. M. Fenwick. A new data structure for cumulativefrequency tables. Software: Practice and Experience, 1994.

[8] M. L. Fredman. A lower bound on the complexity oforthogonal range queries. J. ACM, 1981.

[9] M. L. Fredman. The complexity of maintaining an array andcomputing its partial sums. J. ACM, 1982.

[10] H. Garcia-Molina, J. D. Ullman, and J. Widom. DatabaseSystems: The Complete Book. 2008.

[11] S. Govindarajan, P. K. Agarwal, and L. Arge. Crb-tree: Anefficient indexing scheme for range-aggregate queries. ICDT,2002.

[12] L. J. Guibas and R. Sedgewick. A dichromatic framework forbalanced trees. In Proceedings of the 19th AnnualSymposium on Foundations of Computer Science, 1978.

[13] S. Héman, M. Zukowski, N. J. Nes, L. Sidirourgos, andP. Boncz. Positional update handling in column stores.SIGMOD, 2010.

[14] C. Ho, R. Agrawal, N. Megiddo, and R. Srikant. Rangequeries in olap data cubes. SIGMOD, 1997.

[15] S. Idreos, M. L. Kersten, and S. Manegold. Updating acracked database. SIGMOD, 2007.

[16] J. Krueger, M. Grund, A. Zeier, and H. Plattner. Enterpriseapplication-specific data management. EDOC, 2010.

[17] D. Lemire, O. Kaser, and K. Aouiche. Sorting improvesword-aligned bitmap indexes. Data Knowledge Engineering,2010.

[18] I. Lopez, R. T. Snodgrass, and B. Moon. Spatiotemporalaggregate computation: A survey. IEEE Transactions onKnowledge. and Data Engineering, 2005.

[19] M. Paatrascu and E. D. Demaine. Tight bounds for thepartial-sums problem. SODA, 2004.

[20] M. Stonebraker, D. J. Abadi, A. Batkin, X. Chen,M. Cherniack, M. Ferreira, E. Lau, A. Lin, S. Madden,E. O’Neil, P. O’Neil, A. Rasin, N. Tran, and S. Zdonik.C-store: a column-oriented dbms. VLDB, 2005.

[21] Y. Wang, M. Zhang, J. Li, and L. Zhang. An improvedag-tree based on column store. In International Conferenceon Artificial Intelligence and Education, 2010.

[22] J. Yang and J. Widom. Incremental computation andmaintenance of temporal aggregates. VLDB, 2003.