On Tue, Oct 05, 2010 at 04:08:41AM -0700, Drake Wilson scratched on the wall:
> Quoth Ian Hardingham <i...@omroth.com>, on 2010-10-05 11:52:36 +0100:

> > I'm running this code from a scripting language bound to SQLite:
> > 
> >      %r = db.query("SELECT * FROM userTable", 0);
> >      %i = 0;
> > 
> >      db.query("BEGIN TRANSACTION", 0);
> >      while (%i < db.numRows(%r))
> >      {
> >          %username = db.getColumn(%r, name);
> >          db.query("UPDATE userTable SET playedInfIds='' WHERE name LIKE 
> > '?'", 0, %username);
> >          %i ++;
> >      }
> >      db.query("END TRANSACTION", 0);

> A number of points come to mind fairly immediately:
> 
>   - Don't keep a query from outside a transaction active inside it.

  While this is good advice, I don't think that's what is going on
  here.  The SELECT should definitely be inside the BEGIN/END, because
  otherwise the data may change between the SELECT and UPDATE loop, but 
  that's a different issue.  If I understand this scripting API, the
  query() function will run the SELECT to completion, so any auto-commit
  transaction that is open will be shut again by the time the code
  enters the loop.

  Not that it matters... If the SELECT did open an auto-commit
  transaction that was not closed, a transaction would already be open
  and the BEGIN/END wouldn't change that.  The whole collection of
  statements would be run inside the auto-commit transaction until
  all the statements were complete.

>   - This whole loop looks like it could be replaced with the single
>     query ? UPDATE userTable SET playedInfIds = '' ? because you're
>     just targeting all the rows, unless there's something unobviously
>     different that I've missed.

  Yes... usually the mistake is to forget the WHERE, but in this case
  it looks like the OP actually wants to change every row in the table,
  and that can be done with a single UPDATE statement.... just drop the
  WHERE all together.


  That column name makes me suspicious, however... I have a bad feeling
  that's a text field that is made up of delineated values,
  essentially forming a list.  If true, that's a very poor design.

> Right now you're doing a full table scan to get each name, then doing
> another full table scan for each name to update each row with a
> similar name.  That's O(N^2) in the number of rows; with 3k rows, that
> requires ~9M processing steps.

  It isn't that bad.  He's looking up a PRIMARY KEY without wildcards
  (I assume), so each look-up is O(logN), making the total O(NlogN).
  It is a bloated O(logN) because you're depending on the LIKE
  optimizations, but it is still technically O(logN).  Not good for
  the desired results, which should more or less be O(N), but not
  nearly as bad as O(NN).

> Also, PRIMARY KEY UNIQUE is redundant.  A primary key is always
> unique.

  True, but it does no harm.  SQLite is smart enough to only create one
  index.  The NOT NULL would be redundant in most database systems as
  well, but SQLite requires it for true PK behavior.

   -j

-- 
Jay A. Kreibich < J A Y  @  K R E I B I.C H >

"Intelligence is like underwear: it is important that you have it,
 but showing it to the wrong people has the tendency to make them
 feel uncomfortable." -- Angela Johnson
_______________________________________________
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users

Reply via email to