LINUX.ORG.RU

update в цикле

 ,


0

2

Привет всем. В базах данных я новичок, поэтому всех подводных камней не знаю.

Нужно создавать таблицы примерно в 28 столбцов и 1500 строк или больше. БД нужна для хранения промежуточных вычислений анализа текста. Например, номер слова, само слово, слово в нижнем регистре, слово без пунктуации, формы склонения и т.д. При этом изначально база пустая, и ее надо пополнять не сразу, а в процессе обращения к требуемым элементам (не все элементы требуются, к тому же, экономятся ресурсы). Стало быть, для каждого элемента мне требуется выполнять update.

Почему операция update так долго выполняется, даже если БД создана в памяти? Почитал руководства, многократные update рекомендуется заворачивать в транзакции. У меня тестовая БД 7x1000 генерируется ~2.5 с. Это долго? Как оптимизировать? Пытался завернуть в транзакцию, прироста в производительности не наблюдаю. Пример кода ниже.

#!/usr/bin/python3

import sqlite3
from time import time

class SQLExample:
	
	def __init__(self):
		self._lst = []
	
	def lst(self):
		print('Building list...')
		if not self._lst:
			for i in range(1000):
				self._lst.append(i)
		return self._lst
	
	def create(self):
		self.db_con = sqlite3.connect(':memory:')
		self.db = self.db_con.cursor()
		self.db.execute('PRAGMA synchronous=OFF')
		self.db_con.isolation_level = 'DEFERRED'
		#self.db.execute('PRAGMA journal_mode=OFF')
		self.db.execute('create table WORDS (NO integer,P text,NP text,F_SYM_P integer,L_SYM_P integer,F_SYM_NP integer,L_SYM_NP integer)') # todo: commas before ')'?
		self.db_con.commit()
		
	def fill(self):
		for i in range(len(self.lst())):
			self.db.execute('insert into WORDS values (?,?,?,?,?,?,?)',(i,-1,-1,-1,-1,-1,-1,))
		self.db_con.commit()
		
	def close(self):
		self.db.close()
		
	def update(self):
		print('Updating DB...')
		start_time = time()
		for i in range(len(self.lst())):
			#print('Updating row #',i)
			self.db.execute('update WORDS set P=? where NO=?',(str(self._lst[i]),i,))
			self.db.execute('update WORDS set NP=? where NO=?',(str(self._lst[i]),i,))
			self.db.execute('update WORDS set F_SYM_NP=? where NO=?',(self._lst[i],i,))
			self.db.execute('update WORDS set L_SYM_NP=? where NO=?',(self._lst[i],i,))
			#self.db.executescript('begin; update WORDS set P=%s where NO=%d;update WORDS set NP=%s where NO=%d;update WORDS set F_SYM_NP=%s where NO=%d;update WORDS set L_SYM_NP=%s where NO=%s;commit;' % (str(self._lst[i]),i,str(self._lst[i]),i,str(self._lst[i]),i,str(self._lst[i]),i))
		self.db_con.commit()
		print('Finished in %s.' % str(time()-start_time))
		
	def run(self):
		print('Creating table...')
		self.create()
		print('Filling table...')
		self.fill()
		print('Updating table...')
		self.update()
		self.close()

SQLExample().run()
★★★★★

индекс для NO сделай, но лучше переделай всю логику на insert, это возможно в твоем случае

hizel ★★★★★ ()
Ответ на: комментарий от hizel

индекс для NO сделай

Спасибо, помогло. Уже пытался делать индекс, но не понял, что это эффективнее всего на NO.

но лучше переделай всю логику на insert, это возможно в твоем случае

insert требует одновременного заполнения всех элементов строки, так? Тогда не уверен. Что делать со столбцами, вычисление которых занимает прилично времени? Например, падежи. Лучше вычислить падежи для слов, которые затребованы в данный момент, чем сразу падежи для всех слов в тексте (потому что не обязательно все из них будут использованы).

denton ★★★★★ ()

И зачем тут реляционная бд вообще тут?

invy ★★★★★ ()

попробуй так ) :

update WORDS set P=?, NP=?, F_SYM_NP=?, L_SYM_NP=? where NO=?

drsm ()
Ответ на: комментарий от invy

Какой тип БД нужен при частом обновлении данных?

denton ★★★★★ ()
Ответ на: комментарий от denton

В конкретной задаче БД вообще не нужна. Слово реляционная неспроста. Суть БД в возможности строить зависимости между данными а не просто херачить туда все попало как в мусорку.

invy ★★★★★ ()
Ответ на: комментарий от invy

1. Мне нужно иметь возможность сохранять данные на диске 2. SELECT делается намного быстрее, чем когда я руками по питоновскому словарю прохожу 3. SELECT мне кучу кода экономит

Слово реляционная неспроста

Ну так может быть, не реляционная БД нужна, а другая какая-нибудь?

denton ★★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.