> On 25 May 2012, at 3:04am, IQuant <sql...@iquant.co.cc> wrote:
> 
> > update TICKDATA set IQ_A = ROUND(ASK - (
> >   select t2.ASK from TICKDATA t2
> >   where t2.SYMBOL = TICKDATA.SYMBOL and t2.TIMESTAMP <
> > TICKDATA.TIMESTAMP ORDER BY T2.SYMBOL, t2.timestamp DESC LIMIT 1),4),
> > IQ_B = ROUND(BID - (
> >   select t2.BID from TICKDATA t2
> >   where t2.SYMBOL = TICKDATA.SYMBOL and t2.TIMESTAMP <
> > TICKDATA.TIMESTAMP ORDER BY T2.SYMBOL, t2.timestamp DESC LIMIT 1),4),
> > IQ_T = ROUND(TRADEPRICE - (
> >   select t2.TRADEPRICE from TICKDATA t2
> >   where t2.SYMBOL = TICKDATA.SYMBOL and t2.TIMESTAMP <
> > TICKDATA.TIMESTAMP ORDER BY T2.SYMBOL, t2.timestamp DESC LIMIT 1),4),
> > IQ_X = (select t2.timestamp from TICKDATA t2
> >   where t2.SYMBOL = TICKDATA.SYMBOL and t2.TIMESTAMP <
> > TICKDATA.TIMESTAMP ORDER BY T2.SYMBOL, t2.timestamp DESC LIMIT 1);
> >
> > The consolidated tick database is 1.5GB / 32M records and the above
> > query takes 5 minutes to run.

> On 24 May, 2012 20:11, Simon Slavin said:

> You appear to be doing the same sub-select four times.  I don't know whether
> SQLite optimizes these into one or not, but if you're using a programming
> language I bet you could speed the query up a great deal by doing that
> subselect first, and substituting the results into the UPDATE command.

It doesn't optimize correlated subqueries even with the same subselect criteria 
-- however the btree indexes are already positioned after the first so the next 
three just traverse the same tree already in memory.


However, here are two ways of moving the correlated queries from the inner loop 
to an outer loop:

-- need unique index on TICKDATA (SYMBOL, TIMESTAMP)
-- the view and the trigger can be defined in the database schema once
CREATE VIEW TICKMAX
AS
  SELECT ASK, BID, TRADEPRICE, TIMESTAMP, SYMBOL
    FROM TICKDATA
   WHERE TIMESTAMP = MAX(TIMESTAMP)
GROUP BY SYMBOL;

CREATE TRIGGER TICKMAXUPDATE INSTEAD OF UPDATE ON TICKMAX FOR EACH ROW
BEGIN
  UPDATE TICKMAX
     SET IQ_A = ROUND(ASK - OLD.ASK, 4),
         IQ_B = ROUND(BID - OLD.BID, 4),
         IQ_T = ROUND(TRADEPRICE - OLD.TRADEPRICE, 4),
         IQ_X = OLD.TIMESTAMP
   WHERE SYMBOL = OLD.SYMBOL
     AND TIMESTAMP < OLD.TIMESTAMP;
END;

-- everytime you want to do an update, run this:
UPDATE TICKMAX SET ASK = ASK + 1;



Of course, if you are using a programming language you could do something like 
this:

cr.execute('BEGIN IMMEDIATE;')
for row in cr.execute('''SELECT ASK, BID, TRADEPRICE, TIMESTAMP, SYMBOL
                            FROM TICKDATA
                           WHERE TIMESTAMP = MAX(TIMESTAMP)
                        GROUP BY SYMBOL;'''):
    cr.execute('''UPDATE TICKMAX
                      SET IQ_A = ROUND(ASK - :ASK, 4),
                          IQ_B = ROUND(BID - :BID, 4),
                          IQ_T = ROUND(TRADEPRICE - :TRADEPRICE, 4),
                          IQ_X = :TIMESTAMP
                    WHERE SYMBOL = :SYMBOL
                      AND TIMESTAMP < :TIMESTAMP;''', row)
cr.execute('COMMIT;)

In other words, select the values at the maximum timestamp for each symbol, 
then for each row returned execute the update statement updating the rest of 
the rows for that symbol ... both the trigger and the above code move the 
selection of the updating values from the inner loop to an outer loop.


Of course, they may not make much of a difference at all.  The latter two will 
do exactly count(distinct symbol) less row updates, but that is still pretty 
much every row in the database.  You will have to try it and see if the 
performance increase (if any) is worth the additional complexity.

---
()  ascii ribbon campaign against html e-mail
/\  www.asciiribbon.org


> -----Original Message-----
> From: sqlite-users-boun...@sqlite.org [mailto:sqlite-users-
> boun...@sqlite.org] On Behalf Of 
> To: General Discussion of SQLite Database
> Subject: Re: [sqlite] Update Query
> 
> 
> 
> 
> Simon.
> _______________________________________________
> sqlite-users mailing list
> sqlite-users@sqlite.org
> http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users



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

Reply via email to