Android Cursor maximum size - android

It appears that Cursors in android can only hold up to 1 MB of data.
What would be the most efficient way to pull the maximum number of rows from a table in a SQLite database that stays under the 1 MB limit?

I don't think there's a hard and fast way to determine the right limit, but I looked in the CursorWindow documentation and found that copyStringToBuffer (int row, int column, CharArrayBuffer buffer) seems promising as CharArrayBuffer has a integer field called sizeCopied and the method copyStringToBuffer takes the text at the specified row and column. Maybe you can get the size from the buffer and add for each row and column you have? If you're using SQLiteCursor, you can use setWindow(CursorWindow window) to set your own window.

You can put LIMIT clause, so that rows are fetched in parts.

Related

Android 9(only observed) using Room(for non-images): Row too big to fit into CursorWindow requiredPos=0, totalRows=1

I've only observed this on Android 9 and possibly only on Samsung devices. I'm storing multiple JSON responses to multiple serialized strings into my DB later to be typeConverted using Moshi again into a model.
The query that causes this error is:
#Query(“SELECT * FROM tasks”)
public abstract Flowable<List<TaskEntity>> getAll();
The last instance had a total of about 392,000 characters TOTAL in the table. These are actually split up into about 5500 character size entries within the table.
Why would the cursor have a problem with ~11k byte sized entries? Does the fact that I'm selecting * mean the cursor is grabbing the whole table into memory and not a single row at a time?
Why only Android 9?
Thanks.
Does the fact that I'm selecting * mean the cursor is grabbing the whole table into memory and not a single row at a time?
SELECT * means you are retrieving all columns. A SELECT without a WHERE clause (or other types of constraints) means that you are retrieving all rows. So, SELECT * FROM tasks will attempt to retrieve the entire table contents into memory.
You could add #Transaction to this function, as that may help get past this error. Quoting the documentation:
When used on a Query method that has a SELECT statement, the generated code for the Query will be run in a transaction. There are 2 main cases where you may want to do that:
If the result of the query is fairly big, it is better to run it inside a transaction to receive a consistent result. Otherwise, if the query result does not fit into a single CursorWindow, the query result may be corrupted due to changes in the database in between cursor window swaps.
If the result of the query is a POJO with Relation fields, these fields are queried separately. To receive consistent results between these queries, you also want to run them in a single transaction.
Even better would be to not load the entire table's content's into memory (and then convert the entire table's rows into entity objects). Heap space is limited.
Why only Android 9?
No clue. I wouldn't worry about that — if you focus on retrieving less data, that will have benefits for all your users.

Does SQLite `NOT IN` parameter have any size limit?

I have an SQLite DB where I perform a query like
Select * from table where col_name NOT IN ('val1','val2')
Basically I'm getting a huge list of values from server and I need to select the ones which is not present in the list given.
Currently its working fine, No issues. But the number of values from server becomes huge as the server DB is getting updated frequently.
So, I may get thousands of String values which I need to pass to the NOT IN
My question is, Will it cause any perfomance issue in the future? Does the NOT IN parameter have any size restriction? (like max 10000 values you can check)?
Will it cause any crash at some point?
This is an official reference about various limitation in sqlite. I think the Maximum Length Of An SQL Statement may related to your case. Default value is 1000000, and it is adjustable.
Except this I don't think any limitation existed for numbers of parameter of NOT IN clause.
With more than a few values to test for, you're better off putting them in a table that has an index on the column holding them. Then things like
SELECT *
FROM table
WHERE col_name NOT IN (SELECT value_col FROM value_table);
or
SELECT *
FROM table AS t
WHERE NOT EXISTS (SELECT 1 FROM value_table WHERE value_col = t.col_name);
will be reasonably efficient no matter how many records are in value_table because that index will be used to find entries.
Plus, of course, it makes it a lot easier to re-use prepared statements because you don't have to create a new one and re-bind every value (You are using prepared statements with placeholders for these values, right, and not trying to put their contents inline into a string?) every time you add a value to the ones you need to check. You just insert it into value_table instead.
Yes, there is a limit of 999 arguments as reported in the official documentation: https://www.sqlite.org/limits.html#max_variable_number

Check how much space a single row takes in Sqlite

Is there a way to check how much space a single row takes in Sqlite?
I have tried using this way:
I have 4 fields in my table:
id(int)
name(text)
pat(text)
is_default(bool)
select *, sum(length(id)+length(name)+length(pat)+length(is_default))
from color;
But it returns character length (for example: 43). How can I determine the row length in bytes?
SQLite itself does not give you this information, but the sqlite-analyzer tool does.
If you want to do this from your app, you have to read all the record values and from those deduce how many bytes are used in the on-disk record format.

Little help putting together a delete statement in SqlLite using OrmLite

I have trouble putting together a delete statement in my Android application (I am using OrmLite).
I have a table filled with records. Two of the fields are "dateCreated" (type Date) and "imageSize" (type int). In my code I have a method free(int size). This method tells me that I have to delete oldest records from my table that sum "imageSize" <= size.
For instance .. i get parameter 1000. Each record has value lets say 100. That means i have to delete 10 of the oldest records.
Can some one please provide me with optimal raw SQL statement or even better an OrmLite code for this?
I would be most gratefull.
Unfortunately, you can't do this with a single SQL statement. There is no way to say
select records until their sum is less than X
You could doing multiple queries until you found the oldest records whose sum is less than X but it would take a number of separate SQL calls.
I'd recommend selecting the last X images with their sizes and then doing a delete of the right number of images using a DELETE ... IN .... Here's the pseudo code:
while (true) {
SELECT id, imageSize FROM yourtable ORDER BY dateCreated DESC LIMIT 10;
find the images from the bottom whose sum(imageSize) <= parameter
delete the found images
break if you exceed the parameter otherwise loop and get the next 10
}
try this,
DELETE FROM yourtable WHERE imageSize <= (SELECT SUM(ImageSize) FROM yourtable)
Use the same parameter for your function

is there any max limit for no:of rows while using sqlite?

I have a CSV file which contains around 1200 rows. I was trying to insert it into sqlite db. Around 300 rows only got inserted. Rest didnt...Is there any max limit on no:of rows in a table while using sqlite?
I tried more than 10000 inserts it worked, also check in android market there is SQL performance check tool which makes more inserts.
Rgds
Balaji
Ya.. we can have more than 10000 inserts.. Please refer this link
There IS a max limit for creating rows in SQLite.
If the table is initially empty, then a ROWID of 1 is used. If the
largest ROWID is equal to the largest possible integer
(9223372036854775807) then the database engine starts picking positive
candidate ROWIDs at random until it finds one that is not previously
used. If no unused ROWID can be found after a reasonable number of
attempts, the insert operation fails with an SQLITE_FULL error.
check the official SQLite documentation about Auto Increment.

Categories

Resources