Dan,
First, can I clarify query semantics. SQL is a strongly-typed language, but
there are a couple of ways you can make it work on a “schema-less” or
“schema-on-read” database. The Splunk adapter does it one way (the columns you
ask for effectively become the schema for the duration of that query) and Drill
working on JSON documents does it another way (you get back a record with a
single column whose value is a map, and then you can probe into that map for
values). I guess the former is what people call a key-value database, the
latter a document database.
The next question is what should be your basic table-scan operator. Let’s
assume that you want to pass in a list of columns to project, plus a boolean
expression like ‘c1 > 10 and c1 < 20 and c2 = 4’ for the conditions you want to
be executed in the table scan. (Not sure exactly what expressions rocksdb can
handle, but you should start simple.)
I think I complicated things by trying to pack too much functionality into
SplunkTableAccessRel. Here’s how I would do it better and simpler for your
RocksDB adapter. (And by the way, the MongoDB adapter works more like this.)
I’d write a RocksTableScan extends TableAccessRelBase. Also write a
RocksProjectRel, whose expressions are only allowed to be RexInputRefs (i.e.
single columns), and a RocksFilterRel, which is only allowed to do simple
operations on PK columns. In other words, you write RocksDB equivalents of the
relational operators scan, project, filter, that do no more than — often a lot
less than — their logical counterparts. The mistake in the Splunk adapter was
giving a “table scan” operator too many responsibilities.
Create a RocksConvention, a RockRel interface, and some rules:
RocksProjectRule: ProjectRel on a RocksRel ==> RocksProjectRel
RocksFilterRule: FilterRel on RocksRel ==> RocksFilterRel
RocksProjectRule would only push down column references; it might need to
create a ProjectRel above to handle expressions that cannot be pushed down.
Similarly RocksFilterRule would only push down simple conditions.
Fire those rules, together with the usual rules to push down filters and
projects, and push filters through projects, and you will end up with a plan
with
RocksToEnumerableConverter
RocksProject
RocksFilter
RocksScan
at the bottom (RocksProject and RocksFilter may or may not be present). When
you call the RocksToEnumerableConverter.implement method, it will gather
together the project, filter and scan and make a single call to RocksDB, and
generate code for an enumerable. The rest of the query will be left behind,
above the RocksToEnumerableConverter, and also get implemented using
code-generation.
ArrayTable would be useful if you want to cache data sets in memory. As always
with caching, I’d suggest you skip it in version 1.
Sounds like an interesting project. You ask really smart questions, so I’d be
very happy to help further. And when you have something, please push it to
github so we can all see it.
Julian
On Oct 1, 2014, at 12:57 AM, Dan Di Spaltro <[email protected]> wrote:
> First off, this project is awesome. Great in code documentation.
>
> I am trying to build a sql frontend for rocksdb. The general idea is
> to iterate over a single key/value pairs and build them up to a map, 1
> layer deep.
>
> foo\0bar = v1
> foo\0baz = v2
> f2\0bar = v3
> f2\0baz = v4
>
>
> bar baz
> foo v1 v2
> f2 v3 v4
>
> So I started looking at the Splunk code since it seems like middle of
> the road complexity with projection (unknown columns at metadata time)
> and filter push-down (via the search query). The spark example seemed
> overly complex and the csv example doesn't have anything but
> projection (which is easy to grasp). Here are some of my specific
> trouble areas:
>
> #1 "primary key". with specific columns, I'd like pass them down to
> the db engine to filter. So I've set up the structure very similar to
> the Splunk example, both with projections, filters and filter on
> projections and vice versa. Is there a good pattern to do this
> basically to pass all the stuff I need to push down to the query
> layer? If it's not a pk how do I let the in-memory system do the
> filtering?
>
> #2 "alchemy". There is a lot of alchemy in [1], is it complex because
> you're overloading a single class with multiple functions? Any good
> ideas where I'd learn the top vs bottom projections. That's probably a
> tough question, since I am pretty much a newb at query planning/sql
> optimizers.
>
> #3 "array table". Would that be useful in this situation?
>
> [1]
> https://github.com/apache/incubator-optiq/blob/master/splunk/src/main/java/net/hydromatic/optiq/impl/splunk/SplunkPushDownRule.java#L99
>
> This is really neat stuff,
>
> -Dan
>
> --
> Dan Di Spaltro