On 03/06/2011, at 11:40 PM, Ian Hardingham wrote: > Hey guys, thank you very much for the help so far. > > The list of calls which I make during the "end match section", which can > take 2 seconds, is: > > SELECT * FROM multiturnTable WHERE id=? LIMIT 1 > > UPDATE multiturnTable SET p1SubmitScore=1 WHERE id=? > > UPDATE multiturnTable SET complete=1, score=? WHERE id=? > > SELECT * FROM userTable WHERE name='?' twice > > UPDATE userTable SET totalScore=?, totalRecord='?', dailyScore=?, > dailyRecord='?', dailyGameRecord='?', dailyGamesPlayed='?', > scoreStreak='?', scoreStreakNumber=? WHERE name='?'; twice
If properly constructed, I would expect this to be almost instant. I suggest: 1. Use integer columns instead of text for id primary key 2. Use foreign keys (ie "references") 3. Atomize your columns, ie only one piece of data per column (eg don't store record as number tab number in one column). 4. For any column that is multiple choice (eg status), don't store as text, store as an integer that references another table. 5. In general, properly normalise your tables, which includes the above. It's hard to be more precise without knowing your data better. 5. Use triggers to update the related user table when a match changes (eg ends). 6. Do all of an event in one transaction. 7. Do it all (or as much as possible) of an event in SQL, rather than passing values back from SQL into application then back to SQL. At the basic level, do the foloowing: Change multiturnTable to this (I've only really changed the first three columns): create table multiturnTable ( id integer primary key not null , player1 integer not null references userTable(id) , player2 integer not null references userTable(id) , date text , rating real , info text , complete integer , currentTurn integer , p1Submitted integer , p2Submitted integer , score real , gamemode text , turnLimit integer , turnTimeLimit integer , p1SubmitScore integer , p2SubmitScore integer , quickMatchId integer , nComments integer default 0 , p1TurnSubTime real , p2TurnSubTime float , nRatings integer , p1GivenUp integer , p2GivenUp integer , dupId integer default -1 , p1Declined integer default 0 , p2Declined integer default 0 , lastP1CommitTime text default '-1' , lastP2CommitTime text default '-1' ) ; Change userTable to this: create table userTable ( id integer primary key not null , name text not null unique collate nocase , email text collate nocase , key text , status text , date text , playedFor integer , totalScore real default 0 , totalRecordHigh integer default 0 , totalRecordLow integer default 0 , dailyScore real default 0 , dailyRecordHigh integer default 0 , dailyRecordLow integer default 0 , dailyGameRecordHigh integer default 0 , dailyGameRecordLow integer default 0 , dailyGamesPlayed integer default 0 , scoreStreak text default '' , scoreStreakNumber integer default 0 , noEmail integer default 0 , playedInfIds text default '' ) ; -- These calculations are guesses. You will need to correct them: create trigger multiturnEndMatch after update of complete on multiturnTable when new.complete = 1 and old.complete != 1 begin update userTable set totalScore = totalScore + new.p1SubmitScore , dailyScore = dailyScore + new.p1SubmitScore , dailyGamesPlayed = dailyGamesPlayed + 1 , scoreStreak = scoreStreak + new.p1SubmitScore , scoreStreakNumber = scoreStreakNumber + 1 where id = old.player1 ; update userTable set totalScore = totalScore + new.p2SubmitScore , dailyScore = dailyScore + new.p2SubmitScore , dailyGamesPlayed = dailyGamesPlayed + 1 , scoreStreak = scoreStreak + new.p2SubmitScore , scoreStreakNumber = scoreStreakNumber + 1 where id = old.player2 ; -- if player1 won: update userTable set totalRecordHigh = new.p1SubmitScore , totalRecordLow = totalRecordLow + new.p2SubmitScore where new.p1SubmitScore > new.p2SubmitScore and totalRecordHigh < new.p1SubmitScore ; update userTable set dailyRecordHigh = new.p1SubmitScore , dailyRecordLow = new.p2SubmitScore where new.p1SubmitScore > new.p2SubmitScore and dailyRecordHigh < new.p1SubmitScore ; update userTable dailyGameRecordHigh = new.p1SubmitScore , dailyGameRecordLow = new.p2SubmitScore where new.p1SubmitScore > new.p2SubmitScore and dailyGameRecordHigh < new.p1SubmitScore ; -- if player2 won: update userTable set totalRecordHigh = new.p2SubmitScore , totalRecordLow = totalRecordLow + new.p1SubmitScore where new.p2SubmitScore > new.p1SubmitScore and totalRecordHigh < new.p2SubmitScore ; update userTable set dailyRecordHigh = new.p2SubmitScore , dailyRecordLow = new.p1SubmitScore where new.p2SubmitScore > new.p1SubmitScore and dailyRecordHigh < new.p2SubmitScore ; update userTable dailyGameRecordHigh = new.p2SubmitScore , dailyGameRecordLow = new.p1SubmitScore where new.p2SubmitScore > new.p1SubmitScore and dailyGameRecordHigh < new.p2SubmitScore ; end ; Then your end match SQL becomes simply one SQL statement: update multiturnTable set complete = 1 where id = ? That will fire the trigger to update the user data, which all occurs in one transaction. Another option worth considering is to not store and update the individual user game history data in the userTable at all. You could simply cross reference and perform calculations on the multiturn table when needed. This saves you from having to keep tables in sync and updated, and eliminates redundant data. The speed is potentially slower, but you probably won't notice with indexes on player1 and player2. So, for instance, when wanting the stats for a particular user, you could do this: select userTable.id , userTable.name , sum(player1.p1SubmitScore) + sum(player2.p2SubmitScore) as totalScore , max(max(player1.p1SubmitScore), max(player2.p2SubmitScore)) as totalRecordHigh from userTable left join multiturnTable as player1 on userTable.id = multiturnTable.player1 left join multiturnTable as player2 on userTable.id = multiturnTable.player2 where userTable.id = ? and multiturnTable.complete = 1 ; I hope this helps. Tom BareFeetWare -- Comparison of SQLite GUI tools: http://www.barefeetware.com/sqlite/compare/?ml -- iPhone/iPad/iPod and Mac software development, specialising in databases develo...@barefeetware.com _______________________________________________ sqlite-users mailing list sqlite-users@sqlite.org http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users