On Tue, Jun 28, 2011 at 8:18 PM, Jan Hudec <b...@ucw.cz> wrote:

> On Tue, Jun 28, 2011 at 17:33:23 +0300, Lazarus 101 wrote:
> > Hi guys, i'm working on an Android app and using sqlite to store some
> data
> > and i need some help with a query.
> >
> > I have the following table structure:
> >
> > FILES
> > file_id INTEGER NOT NULL,
>           ^^^^^^^^^^^^^^^^ Do file_ids repeat? If not, it should be
> "integer
>          primary key". Than sqlite will alias the column to the "rowid"
>          column the table is internally ordered by for improved performance
>          looking up by file_id and saving some space (one fewer columns).
>

yes, that was already marked as primary key but it was at the end of the
create statement, that's why i forgot to mention it.


> > name TEXT
> >
> > DATA
> > file_id INTEGER REFERENCES files(resource_id) ON DELETE CASCADE,
> > data_type TEXT,
>
> If nothing else, you want to define integer identifiers for the data types
> and use integer here. That will save you some space (reading from flash is
> still performance bottleneck, especially if the flash is SD card) and some
> unnecessarily costly string comparisons. In code, you'd obviously use
> symbolic constants.
>
> > value TEXT
>
> Obviously you need index on DATA(file_id, data_type, value)
>
> Yes, all three columns. The first two will appear in your query, so have to
> be first two having the result also included in the index saves time,
> because
> now everything can be obtained from the index and the table itself does not
> have to be fetched.
>

I will try this, thanks.


>
> > data_type can be one of:
> > (title, description, date_taken, latitude,longitude, duration,
> > album,track_nr,genre, artist, year)
>
> Why this "hypernormalized" structure. When the set is fixed and there can
> be
> only one of each for each file, a big table with one column for each
> attribute will do you much better service.
>

it's not fixed, for photos for example it's possible that we would want to
add some other exif values, also some mp3 tags can have more then one value
(artist, genre).


>  Just create FILES with
>    file_id integer primary key,
>    name text,
>    title text,
>    description text,
>    date_taken text, /* or integer if you decide to store timestamps instead
> */
>    latitude number,
>    longitude number,
>    duration number,
>    album text,
>    track_nr integer,
>    genre text,
>    artist text,
>    year integer
>

The files table has some other fields, I only mentioned those that I want in
the result (there is also a path, favorite flag, parent_id, size,state etc.
10 columns in total), so I don't think a table with 20+ columns is a good
idea, also there is the problem of adding new data types that would require
altering the files table structure. And most of the time when I display the
files list i don't need these specific media fields.



>
> > it's possible that a music from files does not have any data associated
> with
> > it, in this case i want the name to be in the result set
> >
> > This has to run as fast as possible. A left join between these tables is
> too
> > slow, for 10.000 entries it takes around 15 seconds just to navigate
> through
> > the cursor, if I add a where clause selecting only one kind of data then
> it
> > reduces to less than 5 seconds which is acceptable.
>
> Last but not least, "explain query plan" is your friend. If you prefix your
> query with "explain query plan" and run it against the database (you can
> use
> the command-line shell or some management tool), sqlite will tell you what
> tables it would read, in which order, using which indices and how big it
> expects the result set to be.
>
> So create various indices and experiment with tweaking the query and look
> what explain query plan tells you. Reading by primary key is fastest,
> followed by covering index, noncovering index and temporary index or linear
> search are worst (except join by temporary b-tree is near-optimal when you
> are not filtering out anything).
>
> Sqlite before 3.7.4 didn't support temporary indices and temporary b-tree
> joins, so it is much more critical to have good indices in older versions,
> because they did happily regress to quadratic or worse complexity and that
> would take ages to complete.
>
> Oh, and remember to remove the indices you end up not using to save space
> and time needed to keep them up to date.
>

On my Android device sqlite version is  3.7.2
Thanks a lot, i will try the "explain query plan"
_______________________________________________
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users

Reply via email to