There was a recent discussion on an internal mailing list asking whether you could set up 10,000 range indexes on a database. When faced with a question like this, we should step back and consider the problem we're trying solve. The data set in question has about 1,000 entities, with an expectation that an average of 10 fields related to each entity would need to be indexed. This leads to the question about having 10,000 range indexes.
At first blush, this line of thought suggests relational thinking -- this is natural; that's what most of us learned first. Of course, every index has a cost, regardless of whether the database is MarkLogic, an RDBMS, or another NoSQL database. 10,000 range indexes isn't a good idea in MarkLogic, but know that if you were thinking about setting up that many, there's probably a better solution.
The first question we should consider is whether we actually need range indexes for those 10,000 fields (elements). MarkLogic's Universal Index may provide what's needed already: indexing the terms and structure of all documents. Through the Universal Index, we can do full-text searches on any ingested content, even scoping it to particular document sections if we want. In many cases, this means we don't need to set up specific indexes to provide rapid access to particular content.
The Universal Index provides immediate access to text and structure. When do we need range indexes? In a search context, we use range indexes for data-type specific inequalities, such as "find me all articles published since Jan 1, 2012". By having a date range index on the publication date, we can build a greater-than-or-equal-to query. We can also use range indexes to get lists of values, enabling us to build facets. Jason Hunter's Inside MarkLogic Server lists other range index benefits.
In typical applications, we want to search across many (or all) fields, but we don't need inequality comparisons or to generate thousands of facets. This means that for most applications, we'll get much of our search capability from the Universal Index and supplement with a small number of range indexes.
In MarkLogic, a field is a structure that lets us refer to the contents of multiple elements by the same name. When we merge data from different sources, we sometimes get multiple elements that represent the same thing, but with different names. For instance, consider two book databases, where one has "published-date" and one has "pub-date". At first glance, these appear to be two separate types of data, suggesting separate range indexes. However, with MarkLogic's field feature, a single name can refer to the contents of both elements, with one type-specific index pulling values from all the elements. This is another way that the number of indexes can be reduced.
Sometimes you really do want to do range queries across a wide variety of fields. In an extreme case, MarkLogic lets you represent everything as triples, allowing for inequality queries using SPARQL's FILTER or the cts:triples() function. MarkLogic's own history monitoring is built entirely with triples. More commonly, triples are used in combination with documents to produce a powerful hybrid.
Why Not 10,000 Range Indexes?
Having looked at some alternatives to setting up 10,000 range indexes, let's come back to the original question. It turns out that the answer is no, you should not attempt to make anything on the order of 10,000 -- a target cap for range indexes should be about 100, with the vast majority of applications requiring a much smaller number than that. Each forest stores the indexes that relate to the content in that forest; each forest is broken into one or more stands. Each of these stands manages its indexes in two memory-mapped files per index. We commonly see 12 forests on a host (six master, six replica) with about 100 stands; multiply that by 10,000 range indexes and we'd have millions of open files handles.
Sometimes the transition from the relational model to the document + triples model doesn't click for a person right away, which can lead to a question like this one. If you find yourself planning to make thousands (or even hundreds) of range indexes, it's probably worth stepping back and rethinking about how the data will be represented. The Universal Index is really powerful -- let it do what it does best! Then for cases the Universal Index doesn't satisfy, apply fields, range indexes, and triples as needed.