我必须查询三个表,并将数据显示给我的customerView。
我的代码是这样的:
Log.v(TAG, System.CurrentTimeMillis())
int len = cursor.getCount();
Log.v(TAG, System.CurrentTimeMillis())
Product[] products = new Product[len];
int i = 0;
while(cursor.moveToNext()){
products[i] = new Product(cursor.getstring(0),.....);
}
Log.v(TAG, System.CurrentTimeMillis())
Sqlite查询:
String sql = "SELECT T1.PRODUCT_ID, CODE, SHORT_DESCRIPTION, CATEGORY_CODE,
BRAND_CODE, FORM_CODE, DENOMINATOR, T1.PIECE_PRICE, T1.lowest_piece_price,
T2.sku_type, T1.master_sku " +
"FROM CUSTOMER_PROD_LIST_ITEMS T1 INNER JOIN PRODUCT T2 ON
T1.PRODUCT_ID = T2.ID INNER JOIN PRODUCT_UOMS ON T2.ID =
PRODUCT_UOMS.PRODUCT_ID"+
"WHERE T1.VALID = 1 AND PRODUCT_UOMS.VALID = 1 AND
CUSTOMER_PRODUCT_LIST_ID = " + customer_pdtlist_ID + "
ORDER BY T1.PRODUCT_ID ASC";
在我测试之后,如果光标中有1500个,我们必须花费超过30秒来完成这一行(cursor.getcount())。如果我删除此行,并使用ArrayList进行。我可以发现我们应该为Cursor.moveToNext()花费超过30秒。
所以我的问题是为什么第一次光标操作需要这么长时间?我们如何解决?
这个人有同样的问题Poor SQLite implementation? First time data access way too slow。但答案对我不起作用。 顺便说一句,我发现在Iphone中显示相同的1500个,只需要3s。
提前感谢!!
答案 0 :(得分:15)
这是为什么光标上的第一个操作太慢的原因。当SQLite支持Cursor时,Android在内部使用sqlite C库,创建Cursor
类似于在C库中创建预准备语句。创建预准备语句很便宜,并且不执行任何查询。取自C库的文档:
<强> sqlite3_prepare()强>
此例程将SQL文本转换为预准备语句对象,并返回指向该对象的指针。此接口需要先前调用sqlite3_open()创建的数据库连接指针和包含要准备的SQL语句的文本字符串。 此API实际上不会评估SQL语句。它只是准备用于评估的SQL语句。
当您在moveToNext()
上致电Cursor
时,就会执行查询实际。 moveToNext
导致调用C库中的sqlite3_step()
函数。再次,取自文档:
<强> sqlite3_step()强>
此例程用于评估先前由sqlite3_prepare()接口创建的预准备语句。对语句进行评估,直至第一行结果可用。要前进到第二行结果,再次调用sqlite3_step()。继续调用sqlite3_step()直到语句完成。不返回结果的语句(例如:INSERT,UPDATE或DELETE语句)在单次调用sqlite3_step()时运行完成。
因此,懒惰地创建Cursor并且仅在首次移动光标时评估查询。
要找出查询花费这么长时间的原因,请在查询中使用EXPLAIN QUERY PLAN
并查看瓶颈所在的位置。通常情况下,缺乏适当的指数。
答案 1 :(得分:1)