Я пытаюсь создать базу данных (используя SQLite в C#) с таблицей для хранения предложений, таблицей для хранения каждого отдельного слова, которое используется в этих предложениях, и таблицей соединения, которая связывает слова к предложениям, которые они появляются. Затем я пытаюсь заполнить базу данных более чем 15 миллионами предложений. По моим оценкам, в моем коде происходит около 150 миллионов вставок. Прямо сейчас, мой код выполняет всего пару сотен предложений в секунду, что займет много времени, чтобы пройти через этот огромный набор данных. Как я могу сделать это быстрее?Оптимизация запросов sqlite insert
Я пробовал помещать все в одну транзакцию, но я не уверен, что это может работать из-за огромного объема данных. Поэтому я использую одну транзакцию для каждого предложения.
Таблицы:
CREATE TABLE sentences (sid INTEGER NOT NULL PRIMARY KEY, sentence TEXT);
CREATE TABLE words (wid INTEGER NOT NULL PRIMARY KEY, dictform TEXT UNIQUE);
CREATE TABLE sentence_words(sid INTEGER NOT NULL, wid INTEGER NOT NULL, CONSTRAINT PK_sentence_words PRIMARY KEY (sid, wid), FOREIGN KEY(sid) REFERENCES Sentences(sid), FOREIGN KEY(wid) REFERENCES Words(wid));
Код:
while ((input = sr.ReadLine()) != null) //read in a new sentence
{
tr = m_dbConnection.BeginTransaction();
sql = "INSERT INTO sentences (sentence) VALUES(@sentence)";
cmd = new SQLiteCommand(sql, m_dbConnection);
cmd.Parameters.AddWithValue("@sentence", input);
cmd.ExecuteNonQuery();
dict_words = jutils.onlyDict(input); //convert all words to their 'dictionary form'
var words = dict_words.Split(' ');
foreach (var wd in words) //for each word
{
sql = "INSERT or IGNORE INTO words (dictform) VALUES(@dictform)";
cmd = new SQLiteCommand(sql, m_dbConnection);
cmd.Parameters.AddWithValue("@dictform", wd);
cmd.ExecuteNonQuery();
sql = "INSERT or IGNORE INTO sentence_words (sid, wid) VALUES((SELECT sid FROM sentences WHERE sentence = @sentence), (SELECT wid FROM words WHERE dictform = @dictform))";
cmd = new SQLiteCommand(sql, m_dbConnection);
cmd.Parameters.AddWithValue("@sentence", input);
cmd.Parameters.AddWithValue("@dictform", wd);
cmd.ExecuteNonQuery();
}
tr.Commit();
}
После некоторого тестирования запросов для каждой из моих таблиц кажется, что очень медленная часть - это моя таблица соединений. Чтобы сделать каждую вставку в этой таблице, мне нужно делать выборки через другую огромную таблицу, которая, кажется, является проблемой. Я не очень хорошо знаком с таблицами данных или linq, но я предполагаю, что для создания данных для таблицы соединений мне все равно придется выполнять операции такого же типа, нет? Любые идеи о том, как я упростил бы этот аспект этого? – Zarxrax
В моем случае было всего 10 ~ 30 тысяч строк, но я сдался. Вам лучше знать, что это «times x numbers of rows», независимо от того, как маленькое слово с 1 столбцом. Итерирование миллионов раз физического подключения к SQL будет продолжаться вечно. Если вам нужно иметь дело с базой данных SQL, вам лучше ознакомиться с DataTable, LINQ, Subquery, BulkCopy, BulkUpdate, LINQtoSQL.Изменение миллионов раз «один за другим» будет быть ночным кошмаром. –
Обучение занимает всего несколько дней, но исполнение будет действительно удовлетворительным. –