"Doug" <pa...@poweradmin.com> schrieb im
Newsbeitrag news:043201cba22a$f023df40$d06b9d...@poweradmin.com...

> This is where I think the problems will crop up.
> Can you imagine making a
> network round trip for each row fetch, and then for each
> column fetch of each row (sqlite3_column_type,
> sqlite3_column_double, etc).
>
> To avoid that, you would need to fetch a lot (buffer) of data and
> bring it back to the client.  And if the response is large, will
> you page, or keep the transaction open on the server thus
> blocking all other clients?
>
> The devil is always in the details :)

In this case, not really...
One can perfectly work without the DBConnection
(SQLites DB-Hdl) on the clientside.

Read-Mode:
The only thing the SQLite-API needs in addition to support
an "RPC-AppServer-mode" better (but also worthwhile for
normal, "connected mode", e.g. for back-forward-navigation),
is a new to introduce resultset-container-object (or struct).
Just a "convenience-addition" in analogy to:
  sqlite3_get_table
  sqlite3_free_table
But instead of delivering an Row/Col-array of "sidewards allocated"
UTF8-string-pointers as the 2D-set - it could work in a way
similar to what for example my wrapper implements in its
cRecordset-Class.

I've done (already years ago) my performance-tests for that,
and by far the best (fastest) approach was, to allocate memory
vertically!, meaning in "stripes per column" (respecting the
expected storage-class of the column in question) - and *not*
a recordwise (horizontally) allocated chunk for each row.
For each column I reallocate (growing by a factor of ~1.5,
to avoid reallocs in each and every sqlite-step) usually two
different memory-areas ...:
e.g. for a "double-storage-class-column":
   an ubyte array for Null- and "unexpected storageclass"-Flags
   a double array which holds the non-null values
or for the blobs- and string-storage-class:
   an ubyte array for Null- and "unexpected storageclass"-Flags
   an "UTF8-stream-array", which contains concatenated Field-Values
   a ulong array for the start-offsets within the UTF8-stream
for the integer-storage-class, I assume signed int8 first,
   until the first value appears, which does not fit  into
   signed int8 anymore - in this case an "elevation" of
   the allocated array-area is performed (moving over all
   the previous values in a small cast-loop).
   The stages in this elevation-mechanism are int8, int32, int64 -
   this way especially the boolean-flag-columns (fitting into int8)
   don't take up that much memory.

As mentioned above, there's already a flagging-mechanism
for unexpected storage-class-values, which could either
be "forced" into the expected storage-class (according to
a mapper-set of column-type-descriptions) - or just
converted to string and stored in a "sparse-matrix-area"
of  the resultset, to be able to deliver such values later
on anyways (over a Binary-Lookup on a RowIdx/ColIdx-
key).

So in addition to:
  sqlite3_get_table
  sqlite3_free_table
We could use an accompanying and fast resultset-api as:
  sqlite3_get_resultset
     sqlite3_resultset_get_recordcount
     sqlite3_resultset_get_columncount
     sqlite3_resultset_get_columninfo(hRs, ColIdx, colInfoEnum)
     sqlite3_resultset_get_value(hRs, RowIdx, ColIdx, strgTypeEnum)
  sqlite3_free_resultset

Coming back to the RPC-stuff again:
The idea to have an encapsulation of vertically allocated
memory-stripes per column in such an resultset is not
only fast in normal Desktop-Mode (in delivering a "typed
copy of a Select" - together with a bunch of useful column-
infos, retrievable e.g. over: "Select * From T Where 0"),
the main-advantage of this kind of mem-alloc-scheme
comes into play within additional functions like that:
    sqlite3_resultset_serialize(hRs, *pBytes)
    sqlite3_resultset_deserialize(*pBytes, *hRs)
Instead of looping over single fields (or records), to build up
a resulting bytestream-serialization, it is now much faster, to loop
over the columnwise allocated chunks and concatenate these
in the resulting serialized byte-stream - and the allocation for
the resulting bytestream can now be done *once* (without
any needed reallocs) since all the column-stripe-sizes are
known beforehand.

As said, all this is not made "out of thin air" - this is
(basically) the implementation I'm working with in my
wrapper-classes in dhRichClient3.dll, which contains
classes for a DCOM-like AppServer-Mode too.
Able to deliver thousands of resultsets per second
over worker-objects, hosted in a threadpool.

What my serializable ResultSet-implementation supports
additionally, is a "CreateTableFromContent" method,
which I use often, to "beam up" a freshly received
serialized resultset-stream directly into a clientside
(usually InMemory-DB-) table.
sqlite3_resultset_deserialize_to_table(*pBytes, DbHdl, tblName)

So, for a reliable (and simple) servermode, Sylvains
suggestion is (from my practical experience) perfect for
SQLite.
Keep the sqlite-api "as is" - maybe introduce the roughly
outlined resultset-API directly into the sqlite-core-lib
(for convenience-benefits not only in RPC-mode) -
and then a ("loosely attached to the SQLite-project")
implementation of a multithread- (or multi-process)
RPC-server could be written - in a way that
resembles somewhat to the Fossil-implementation.

A standalone-executable, able to deliver serialized
resultsets already (and to receive and parse SQL-
Execute-Commands, to support simple write-transactions)
and for "more advanced stuff" such a server could support
"RPCs of any kind" too, against Dlls which are placed
beside the executable at the serverside, and which one
could call dynamically from the clientside then "by name".

RpcHdl = rpc_connect(IP, Port, optUserName, optPassWord, optMode)
errResult = rpc_doroundtrip(RpcHdl, DllName, FunctionName,
                                           pResult, serializedParamSet)

This way also more advanced transactions at the serverside
could be covered.

Just my 2ct.

Olaf



_______________________________________________
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users

Reply via email to