On Thu, Jul 6, 2017 at 12:54 PM, Clemens Ladisch <[email protected]> wrote:
> Dominique Devienne wrote:
> > with
> > kcounts(t, c) as (
> > select code_type, count(*)
> > from keys
> > group by code_type
> > ),
> > ...
> > select ...,
> > (select c from kcounts where t = 'SET') as "#sets",
> > (select c from kcounts where t = 'CST') as "#constants",
> > (select c from kcounts where t = 'CMT') as "#comments",
> > (select c from kcounts where t = 'LOG') as "#logs",
> > ...;
> >
> > the SQL as written does several passes over kcounts
>
> However, the subquery is flattened: each pass counts only rows with
> a specific code_type value.
>
> An index on code_type would help _very much_.
Actually not that much apparently.
No Simon, I didn't have an index on code_type.
In fact keys is itself a view, and cote_type a case expression.
That's fine, I created a expression index using
create index idx_keys_code on keys_tab(
case
when (code & 1) = 1 then 'SET'
when (code & 2) = 2 then 'CST'
when (code & 4) = 4 then 'CMT'
when (code & 8) = 8 then 'LOG'
else null
end
)
The plan correctly changes to "SCAN TABLE keys USING INDEX idx_keys_code",
4x.
And the runtime only drops to ~5.4s closer to 6.5s than 2.15s,
but at the cost of 22MB extra in the DB file for the index. Not sure that a
good tradeof.
> Is there a way to reformulate this query differently to somehow achieve a
> > single pass on the keys table? Or force the query planner to
> "instantiate"
> > the kcounts "CTE view" to achieve that single scan, via some kind of
> hint?
>
> It would be possible to prevent the subquery flattening
> (http://www.sqlite.org/optoverview.html#flattening), but AFAIK there is
> no hint that would force SQLite to recognize that all the instances of
> kcounts are then identical and can be reused.
>
> You could put kcounts into a temporary table.
>
I could it in a table, but then who updates kcounts when keys (or keys_tab)
changes?
I guess one can play with triggers then, to emulate materialized views,
opening a new can of worm.
These are "persistent report views", as already discussed when the thousand
separator was added to printf.
"Users" just "view" these views in any SQLite clients, typically a GUI one.
And they should remain "dynamic"
into case the table contents are modified with DMLs.
Maybe the "hint" to create an ephemeral table for a "CTE view" could be to
prefix the CTE view name with temp. ?
I know that Richard/SQLite are not much into planner hints, but a few
exists already.
What do you think Richard? --DD
> with
> temp.kcounts(t, c) as (
> select code_type, count(*)
> from keys
> group by code_type
> ),
> ...
> select ...,
> (select c from kcounts where t = 'SET') as "#sets",
> (select c from kcounts where t = 'CST') as "#constants",
> (select c from kcounts where t = 'CMT') as "#comments",
> (select c from kcounts where t = 'LOG') as "#logs",
> ...;
_______________________________________________
sqlite-users mailing list
[email protected]
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users