【问题标题】:Android Sqlite insert speed when query for duplicates查询重复项时的Android Sqlite插入速度
【发布时间】:2014-12-06 14:55:25
【问题描述】:

下面的代码在一个异步任务中,它通过互联网获取 csv 文件,然后解析它们并将它们添加到 sqlite 数据库。

因此,在添加任何新行之前,我需要检查它们是否已存在于数据库中。

我的问题是,使用重复检查代码每个 csv 文件需要 2.5 分钟,但如果没有检查,每个文件需要 6 秒。

请问有什么线索可以加快重复检查的速度吗?

  public class GetData extends AsyncTask<String, String, String> {

    @Override
    protected String doInBackground(String... params) {

        //for each csv file
        for (int x = 0; x < 11; x++) {
            get_config("sen" + x + "data.csv");
        }

        return null;
    }



    private void get_config(String siteurl) {

    StringBuilder total = new StringBuilder();

        String mfolder = Environment.getExternalStorageDirectory().getPath() + "/HG";
        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mcontext);
        String basesiteurl = prefs.getString("site_url", "");


        if (!DetectConnection.checkInternetConnection(mcontext)) {
            write_alertlog("AlertService: Fetch csv data - No internet connection");
        }else{

            write_alertlog("AlertService: Fetch csv data - Internet connection success");

            String onlineupdateline = "";
            try {

              Random randomGenerator = new Random();
              int randomInt = randomGenerator.nextInt(100); //defeat android cache

              DefaultHttpClient httpclient = new DefaultHttpClient();
              HttpGet httppost = new HttpGet(basesiteurl + "/csv/" + siteurl + "?unused=" + randomInt);
              HttpParams httpParameters = new BasicHttpParams();
              HttpConnectionParams.setConnectionTimeout(httpParameters, 8000);
              HttpConnectionParams.setSoTimeout(httpParameters, 8000);
              HttpResponse response = httpclient.execute(httppost);
              HttpEntity ht = response.getEntity();

              BufferedHttpEntity buf = new BufferedHttpEntity(ht);
              InputStream is = buf.getContent();
              BufferedReader r = new BufferedReader(new InputStreamReader(is));


              //reformat csv filename into sensor name for db
              String sensor_name = siteurl.replace("data.csv", "");

                database.beginTransaction();
                String line;
                while ((line = r.readLine()) != null) {
                    //total.append(line + "\n");

                    if (line.contains("<!DOCTYPE")){
                        write_applog("AlertService: Fetch csv data - csv file empty or does not exist: " + siteurl);
                        Log.d("test", "csv file empty or does not exist: " + siteurl);
                        database.endTransaction();
                        is.close();
                        r.close();
                        return;
                    }

                    List<String> singlecsvline = new ArrayList<String>(Arrays.asList(line.split(",")));

                    //csv date format
                    SimpleDateFormat fmt = new SimpleDateFormat("EEE MMM dd HH:mm:ss yyyy");
                    Date pi_date = null;
                    try {
                        pi_date = fmt.parse(singlecsvline.get(0).toString().trim());
                    } catch (ParseException e) {
                        e.printStackTrace();
                    }

                    //database date format
                    fmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    String db_dateString = fmt.format(pi_date);
                    Date d = null;
                    try {
                        d = fmt.parse(db_dateString);
                    } catch (ParseException e) {
                        e.printStackTrace();
                    }
                    long db_dateLong = d.getTime();

                    //check if not in db already and if not add it
                    //this duplicate check makes processing each csv file go from 6 secs to 2.5 minutes
                    sql = "SELECT * FROM sensordata WHERE sensor_date='" + db_dateLong + "' AND sensor_id='" + sensor_name + "'" ;
                    Cursor findrawdata2 = database.rawQuery(sql, null);
                    if (!findrawdata2.moveToFirst()) {
                        database.execSQL("INSERT INTO sensordata (sensor_id, sensor_date, sensor_value, alerted, setflag) VALUES ('" + sensor_name + "', '" + db_dateLong + "', '" + Double.parseDouble(singlecsvline.get(1).toString().trim()) + "', '0', '" + setflag + "');");
                    }else{
                        //Log.d("test", "Not Adding - exists");
                    }
                    findrawdata2.close();

                }//for each line in csv file
                database.setTransactionSuccessful();
                database.endTransaction();

                is.close();
                r.close();
                write_applog("AlertService: Fetch csv data - added sensor " + siteurl);
                Log.d("test", "finsihed adding csv sensor " + siteurl);


            } catch (ConnectTimeoutException e) {
                write_alertlog("AlertService: Fetch csv data - Internet connection request timed out >6000ms");
            } catch (MalformedURLException e) {
                write_alertlog("AlertService: Fetch csv data - Error - " + e.toString());
            } catch (IOException e) {
                write_alertlog("AlertService: Fetch csv data - Error - " + e.toString());
            }

        }//have internet connection


        return;
    }

【问题讨论】:

    标签: android performance sqlite


    【解决方案1】:

    如果您只是想检查它是否存在,实际上不需要从数据库中加载一行;使用类似 EXISTS 或 helper function:

    long count = DatabaseUtils.queryNumEntries(database, "sensordata",
                    "sensor_date = " + db_dateLong + " AND sensor_id = ?",
                    new String[]{ sensor_name });
    if (count > 0) {
        ...
    

    但是,最大的减速来自搜索数据库中的行。 您需要为搜索列建立索引以获得快速查找:

    CREATE INDEX insert_name_here ON sensordata(sensor_date, sensor_id);
    

    【讨论】:

    • 谢谢,我添加了 databaseutils 示例,但是 db_dateLong、sensor_name 不是两个字符串 []。 db_dateLong 很长,sensor_name 是字符串。有办法解决吗?
    • 您在查询中将其用作字符串。
    • 数据库是 int 而 var 是 long 类型不匹配:无法从 long 转换为 String
    猜你喜欢
    • 2012-10-28
    • 1970-01-01
    • 1970-01-01
    • 2014-08-10
    • 1970-01-01
    • 2019-02-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多