Гость
Форумы / Android [игнор отключен] [закрыт для гостей] / AsyncTask SQLite / 16 сообщений из 16, страница 1 из 1
08.04.2015, 14:46
    #38930579
НикоДимиден
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
AsyncTask SQLite
Здравствуйте! У меня в приложении есть БД SQLite, при нажатие на кнопку загрузки, приложение начинает в базу вносить записи.
Структура базы :
1.таблица-одна, колонка - одна
2.Кол-во записей : 20 000
3.Формат записи: String до 10 символов.

Метод добавления : через бэкграунд, фоновый поток, используя наследования класса "AsyncTask"


Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
class MyTask extends AsyncTask<Void, Integer, Void> {
	
		@Override
		protected void onPreExecute() {
			super.onPreExecute();
			Info.setText("Начали ");
		}

		@Override
		protected Void doInBackground(Void... params) {
			int counter = 0;
			try {			
				for(int i=0; i<20000;i++){		
		                        getFloor(counter);
					publishProgress(++counter);
			     	}	
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			return null;
		}

		@Override
		protected void onProgressUpdate(Integer... values) {
			super.onProgressUpdate(values);
			Info.setText("Позиция : " + values[0]);
			horizontalprogress.setProgress(values[0]);
		}
		
		@Override
		protected void onPostExecute(Void result) {
			super.onPostExecute(result);
			Info.setText("Загрузили");	
		}
		
		
		private void getFloor(int floor) throws InterruptedException {
	           // Метод 1: INSERT через класс CONTENTVALUE
                   ContentValues cv = new ContentValues();
                   cv.put("time", "Hello "+floor);
                  // вызываем метод вставки
                  Asqdb1.insert("alarm_table",null, cv);
		}
		
		
	}



При занесения записей в базу, уходит около 10-20 минут. Подскажите пожалуйста, нормальная ли это ситуация, когда так долго происходит добавления записей в БД?
Я понимаю что в фоновом потоке задачи выполняются медленнее. Но всё таки, мне кажется что то слишком долго.
...
Рейтинг: 0 / 0
08.04.2015, 14:55
    #38930596
chpasha
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
AsyncTask SQLite
не нормально.
1) стартовать транзакцию до начала вставки, коммитить либо совсем в конце, либо каждые несколько тысяч записей (в конце или нет, зависит от задачи - т.е. устраивает, что вставится 4000 записей а потом по ошибке отвалится или нет)
2) используй InsertHelper или SQLiteStatement
...
Рейтинг: 0 / 0
08.04.2015, 14:55
    #38930597
wadman
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
AsyncTask SQLite
Вставлять нужно порциями...
Перед началом вставки порции явно открой транзакцию и затем явно закрой. Порции подбираются опытным путем. Я обычно делаю 1000. Проблема в том, что без этого транзакции стартуют и заканчиваются на каждый чих (вставку).

Ну и вставлять лучше через SQLiteStatement , а не через ContentValues.
...
Рейтинг: 0 / 0
08.04.2015, 14:56
    #38930600
wadman
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
AsyncTask SQLite
chpashaне нормально.
1) стартовать транзакцию до начала вставки, коммитить либо совсем в конце, либо каждые несколько тысяч записей (в конце или нет, зависит от задачи - т.е. устраивает, что вставится 4000 записей а потом по ошибке отвалится или нет)
2) используй InsertHelper или SQLiteStatement
Хм...
...
Рейтинг: 0 / 0
08.04.2015, 15:00
    #38930614
chpasha
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
AsyncTask SQLite
wadmanХм... это называется на кнопке обошел :)
...
Рейтинг: 0 / 0
08.04.2015, 16:15
    #38930764
Микола Питерский
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
AsyncTask SQLite
Использованием общей транзакции ты увеличишь скорость вставки раза в 2.
Кури PRAGMA synchronous = 0 | OFF | 1 | NORMAL | 2 | FULL;
Этот сервак по умолчанию стоит в FULL - т.е. записывает КАЖДОЕ изменение на диск без кэширования, что и тормозит загрузку.
Перед массовой заливкой нужно передать PRAGMA synchronous OFF, после заливки "вернуть все на место". Вот тогда база SQLite летает - я когда-то грузил в нее несколько тысяч записей в секунду.
...
Рейтинг: 0 / 0
08.04.2015, 16:57
    #38930848
wadman
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
AsyncTask SQLite
Микола ПитерскийВот тогда база SQLite летает - я когда-то грузил в нее несколько тысяч записей в секунду.
На средненьком смартфоне?
...
Рейтинг: 0 / 0
08.04.2015, 17:01
    #38930856
НикоДимиден
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
AsyncTask SQLite
wadman,

УХХХ!!Ты!!! Спасибо!
Скорость возросла в ДЕСЯТКИ РАЗ!!!! с 15-20 минут до 25 секунд!!!
Использовал транзактицию.
Еще сделаю метод добавления информации в базу данных, через SQLiteStatement, посмотрим насколько еще возрастет скорость.



Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
class MyTask extends AsyncTask<Void, Integer, Void> {
	
		@Override
		protected void onPreExecute() {
			super.onPreExecute();
			Info.setText("Начали ");
		}

		@Override
		protected Void doInBackground(Void... params) {
			int counter = 0;
                       //Открывает транзакцию
                       Asqdb1.beginTransaction();
			try {			
				for(int i=0; i<20000;i++){		
		                        getFloor(counter);
					publishProgress(++counter);
			     	}
                    	 //Одобряет транзакцию (Не знаю зачем это нужно (: )
                         Asqdb1.setTransactionSuccessful();
			} catch (InterruptedException e) {
				e.printStackTrace();
			} finally {
				//закрываем транзакцию
				Asqdb1.endTransaction();	
			}


			return null;
		}

		@Override
		protected void onProgressUpdate(Integer... values) {
			super.onProgressUpdate(values);
			Info.setText("Позиция : " + values[0]);
			horizontalprogress.setProgress(values[0]);
		}
		
		@Override
		protected void onPostExecute(Void result) {
			super.onPostExecute(result);
			Info.setText("Загрузили");	
		}
		
		
		private void getFloor(int floor) throws InterruptedException {
	           // Метод 1: INSERT через класс CONTENTVALUE
                   ContentValues cv = new ContentValues();
                   cv.put("time", "Hello "+floor);
                  // вызываем метод вставки
                  Asqdb1.insert("alarm_table",null, cv);
		}
		
		
	}
...
Рейтинг: 0 / 0
08.04.2015, 17:05
    #38930869
wadman
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
AsyncTask SQLite
НикоДимиденУХХХ!!Ты!!! Спасибо!
А я-то что? chpasha был быстрее меня.
...
Рейтинг: 0 / 0
08.04.2015, 17:13
    #38930888
НикоДимиден
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
AsyncTask SQLite
wadman,
Да всем спасибо, кто откликнулся! :)
...
Рейтинг: 0 / 0
08.04.2015, 21:50
    #38931180
НикоДимиден
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
AsyncTask SQLite
С использованием класса SQLiteStatement, стало работать ещё быстрее почти в два раза. Вместо 24 секунд, 13 =)


Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
SQLiteStatement cv;
@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

     //Инициализация
     cv = Asqdb1.compileStatement("INSERT INTO alarm_table (time) VALUES (?)");


}

class MyTask extends AsyncTask<Void, Integer, Void> {
	
		@Override
		protected void onPreExecute() {
			super.onPreExecute();
			Info.setText("Начали ");
		}

		@Override
		protected Void doInBackground(Void... params) {
			int counter = 0;
                       //Открывает транзакцию
                       Asqdb1.beginTransaction();
			try {			
				for(int i=0; i<20000;i++){		
		                        getFloor(counter);
					publishProgress(++counter);
			     	}
                    	 //Одобряет транзакцию (Не знаю зачем это нужно (: )
                         Asqdb1.setTransactionSuccessful();
			} catch (InterruptedException e) {
				e.printStackTrace();
			} finally {
				//закрываем транзакцию
				Asqdb1.endTransaction();	
			}


			return null;
		}

		@Override
		protected void onProgressUpdate(Integer... values) {
			super.onProgressUpdate(values);
			Info.setText("Позиция : " + values[0]);
			horizontalprogress.setProgress(values[0]);
		}
		
		@Override
		protected void onPostExecute(Void result) {
			super.onPostExecute(result);
			Info.setText("Загрузили");	
		}
		
		
		private void getFloor(int floor) throws InterruptedException {
	               cv.clearBindings();
			cv.bindString(1,"Hello "+String.valueOf(floor));
			cv.execute();
		}
		
		
	}
...
Рейтинг: 0 / 0
08.04.2015, 22:53
    #38931202
НикоДимиден
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
AsyncTask SQLite
Микола Питерский,

Вы это делали?

SQLiteDatabase.execSQL(“PRAGMA synchronous=OFF”); Изменить способ записи в базу – без “синхронизации”. При выключении данной опции, база данных может быть повреждена при неожиданном сбое системы, либо отключении питания. Однако согласно документации SQLite некоторые операции при выключении данной опции выполняются более чем в 50 раз быстрее.

Это довольно опасно, как по мне.
...
Рейтинг: 0 / 0
08.04.2015, 23:32
    #38931224
НикоДимиден
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
AsyncTask SQLite
По вашим рекомендациям я разделил добавления информации на некие ячейки, и теперь я добавляю не по одной записи а по 100.
Скорость выросла колоссально!!! Раньше загрузка длилась 15-20 минут, теперь 1,0 - 1,5 секунды. Я доволен)

пример:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
private void getFloor(int floor) throws InterruptedException {
	               cv.clearBindings();
			cv.bindString(1,"Hello "+String.valueOf(floor));
                        cv.bindString(1,"Hello "+String.valueOf(floor+1));
                        cv.bindString(1,"Hello "+String.valueOf(floor+2));
                        cv.bindString(1,"Hello "+String.valueOf(floor+3));
                        //..итд до 100

			cv.execute();
		}



Кстати на заметку. Я прочитал что можно еще воспользоваться NDK и написать код на с++. Тогда будет еще быстрее. Может кому понадобится.
...
Рейтинг: 0 / 0
09.04.2015, 00:02
    #38931240
НикоДимиден
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
AsyncTask SQLite
А не..
7 секунд получилось.
Только я видимо как то не правильно добавляю записи


Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
                        cv.clearBindings();
			cv.bindString(1,"Hello "+String.valueOf(floor+1));
			cv.execute();

                        cv.clearBindings();
			cv.bindString(1,"Hello "+String.valueOf(floor+1));
			cv.execute();

                        cv.clearBindings();
			cv.bindString(1,"Hello "+String.valueOf(floor+1));
			cv.execute();
                     
                 // и так до 100

А вот так две записи не добавляются  :  
                        cv.clearBindings();
			cv.bindString(1,"Hello "+String.valueOf(floor+1));
                        cv.bindString(1,"Hello "+String.valueOf(floor+2));
			cv.execute();

так вылетает с ошибкой:
                        cv.clearBindings();
			cv.bindString(1,"Hello "+String.valueOf(floor+1));
                        cv.bindString(2,"Hello "+String.valueOf(floor+2));
			cv.execute();



Что я делаю не правильно?
...
Рейтинг: 0 / 0
09.04.2015, 09:21
    #38931412
wadman
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
AsyncTask SQLite
НикоДимиден
Код: java
1.
2.
			cv.bindString(1,"Hello "+String.valueOf(floor+1));
                        cv.bindString(1,"Hello "+String.valueOf(floor+2));


Вторая строка замещает предыдущее значение.

НикоДимиден
Код: java
1.
так вылетает с ошибкой:


Наверняка у нее есть текст. Правда, я не заметил разницы между тем примером, что с ошибкой и тем, когда не добавляются две записи...
...
Рейтинг: 0 / 0
09.04.2015, 09:30
    #38931427
Микола Питерский
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
AsyncTask SQLite
НикоДимиденМикола Питерский,

Вы это делали?

SQLiteDatabase.execSQL(“PRAGMA synchronous=OFF”); Изменить способ записи в базу – без “синхронизации”. При выключении данной опции, база данных может быть повреждена при неожиданном сбое системы, либо отключении питания. Однако согласно документации SQLite некоторые операции при выключении данной опции выполняются более чем в 50 раз быстрее.

Это довольно опасно, как по мне.

Ничего опасного - все сервера Кэшируют изменения в буффер и только потом записывают на диск этот буффер, а в SQLite буферизация отключена изначально.
...
Рейтинг: 0 / 0
Форумы / Android [игнор отключен] [закрыт для гостей] / AsyncTask SQLite / 16 сообщений из 16, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]