Hello,

Suppose one has an expression on the columns of a single table, say x +y, and that this expression occurs in multiple queries. Then it is attractive to define it at a single place, using a view:

    create view v as select *, x+y as a from t;

I had hoped that substituting such a view in queries instead of the original table would make performance-wise no difference. This hope is mostly fulfilled but not completely. If the view appears after an OUTER JOIN, there is a difference in the query execution plan. The output is printed below. With the outer join the view is evaluated into a transient table instead of the underlying table being searched directly. This can cause a significant slow down.

I understand that a view is treated by the optimizer as a subquery and that the different execution plan is a matter of Subquery flattening:

    http://www.sqlite.org/optoverview.html#flattening

Apparently the optimizer can not produse a flat query here and that is exactly explained in condition 3:

    3. The subquery is not the right operand of a left outer join.

As a casual reader I would think this only needs to apply if the subquery is not a join. But grasping the complexity of query optimization, there are likely many other bewares, like aggregation, union, sub-subqueries, ordering, limits and where clauses. In my case only the most simple subquery, like the example view, need to be delt with. Is there any chance that just this is recognized by the optimizer?

Desired change in terms of the list of conditions:
    3. The subquery is not the right operand of a left outer join
       or the subquery:
       - is not a join
       - does not use aggregates
       - is not DISTINCT
       - does not use LIMIT
       - does not have a WHERE clause

Does anyone else have the same wish or has this been discussed before?
I would like to know.

Thanks,

Edzard Pasma

Output:
    create table t (t integer primary key, x, y);
    create table t0 (t0 integer primary key, t, z);
    explain query plan
select t.x+t.y from t0 left outer join t using (t) where t0.t0 = 100;
0|0|0|SEARCH TABLE t0 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)
0|1|1|SEARCH TABLE t USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)

    create view v as select *, x+y as a from t;
    explain query plan
    select v.a from t0 left outer join v using (t) where t0.t0 = 100;
1|0|0|SCAN TABLE t (~1000000 rows)
0|0|0|SEARCH TABLE t0 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)
0|1|1|SCAN SUBQUERY 1 (~100000 rows)

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

Reply via email to