[Qgis-developer] in-memory layer as cache in DBManager
mederic.ribreux
mederic.ribreux at medspx.homenet.org
Tue Sep 2 12:04:33 PDT 2014
Hello devs,
during my work on DBManager Oracle implementation, I've been faced with
large layers that take time to open (more than 10 seconds is quite a lot
for the users in my office). It is even worse with dynamic queries
because QGis considers that there is no spatial indexes available (which
is true on most cases). In this situation, it takes the same amount of
time to show a limited set of data and the whole set.
Other GIS tools (ArcGIS 10.x and MapInfo 10.x) provide a very basic
cache feature. Once the layer (or query) content has been loaded in
memory, every operation (scan/pan or geoprocessing) is really fast
(about milliseconds compared to more than 10 seconds). There is no cache
synchronisation mechanisms but it just works (from the user point of
view).
I know that there has been discussions about implementing a cache
mechanism in QGis but I see nothing in the code for the moment (perhaps
am I wrong ?).
I think that for the moment, in-memory layers are the nearest approach
for a cache system. They have been deployed long ago and I think that we
can work with them to offer a very basic-but-easy-to-use cache
mechanism.
I've played so far with Python code to make an in-memory layer from a
(what I think is becoming a) big Oracle table (about 250000 objects).
Performances are quite good: it takes about one second more to build the
in-memory layer than retrieving the whole dataset (17 seconds). Data are
transfered only once during the copy features operation, so the total
amount of time of building the in-memory layer is the time of the query
duration. Once the in-memory layer is loaded, you can pan and zoom at
all levels in less than one second. The only drawback I've found so far
is some freezing on attributes table. It takes about ten seconds to open
the attributes table and scrolling in it is very slow. I've noticed that
when you replace floats fields by integer ones, scrolling is a little
bit faster.
From the user point of view, in-memory layers are similar to a basic
caching system:
- you grab all the data from the SRDBMS the first time you open the
layer.
- Then you are able to do fast data analysis or rendering...
- knowing that if you want to work on true live data, you have to open
the real layer (no synchronisation).
For the moment, the only practical way for a user to build an in-memory
layer is by selecting all the features of a layer (which takes time as
selection launches a refresh query), copy them into clipboard and clip
them in an in-memory layer. Furthermore, this technique doesn't work
with Date/Time attributes (the layer cannot be created).
You can build in-memory copies of a layer by using the Python console
but this is not really user-friendly. I believe that a good entry point
to load an in-memory layer is in DBManager, on the dbtree or in the SQL
editor widget.
Why add this new functionnality there ? First, just because the Python
implementation is easier to code and there will be no modification on
the core code of QGis. Then it seems that the performances will be good.
Furthermore, SQL queries made with the SQL dialog box of the plugin are
good candidates to in-memory layers. Loading them as in-memory layers
can be faster than building them and saving them in a local file (data
are transfered only once from the SRDBMS server).
I'd like to know what do you think about this practical approach of
caching ? Do you think it is a good idea to just add a button or a
checkbox or a menu entry to load a layer or an SQL query as an in-memory
layer ? Do you think DBManager is a good candidate for this user
interface ?
Best regards,
PS: I know that the ideal situation would be a true cache mechanism
directly on core code but (I think) it is far more complex to
implement...
--
Médéric RIBREUX
http://medspx.homenet.org
More information about the Qgis-developer
mailing list