SQLite3を使うと簡単にアプリケーションをつくることができることがわかったのですが、大量のデータを追加した場合、処理が遅くなることはないのでしょうか?
実験用のアプリをつくります。
まず追加するデータをつくります。
これはニュースサイトから拾ってきたものですが、そのまま使うと著作権的に問題があるので、改行や句読点で分割して順序を並べ替えて元の文章がなにかわからないようにしています。これを実行ファイルがあるフォルダにコピーしておきます。
次にアプリケーションが実行されたら10個のテキストファイルを読み込み、これをデータベースのなかによみこみます。この処理は1回やればよいのでテーブルが存在するか調べて存在しないときだけおこないます。
これはテーブルが存在するかどうか調べるメソッドです。
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 |
public partial class Form1 : Form { string DbPath = "test.db"; string TableName = "table_test"; bool IsExistsTable(string tableName) { SQLiteConnectionStringBuilder sqlConnectionSb = new SQLiteConnectionStringBuilder { DataSource = DbPath }; using (SQLiteConnection cn = new SQLiteConnection(sqlConnectionSb.ToString())) { cn.Open(); using (SQLiteCommand cmd = new SQLiteCommand(cn)) { cmd.CommandText = "SELECT * FROM sqlite_master"; using (SQLiteDataReader reader = cmd.ExecuteReader()) { while (reader.Read()) { // テーブルの名前を取得する string name = reader["name"] as string; if (name == TableName) return true; } return false; } } } } } |
これはテキストファイルのデータをSQLite3へ読み込むためのメソッドです。全部で200MBくらいのテキストファイルのデータですが、20秒ちょっとかかりました。全部で1,363,000件あります。
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 66 67 68 69 70 |
public partial class Form1 : Form { void AddListFromFile(List<string> list, string filePath) { // テキストファイルを1行ずつリストのなかに格納する StreamReader sr = new StreamReader(filePath); while (true) { string line = sr.ReadLine(); if (line == null) break; list.Add(line); } sr.Close(); } void AddDataToDB() { // テーブルが存在する場合はデータも読み込まれているのでなにもしない if (IsExistsTable(TableName)) return; // テキストファイルを1行ずつリストのなかに格納する List<string> list = new List<string>(); AddListFromFile(list, "text1.txt"); AddListFromFile(list, "text2.txt"); AddListFromFile(list, "text3.txt"); AddListFromFile(list, "text4.txt"); AddListFromFile(list, "text5.txt"); AddListFromFile(list, "text6.txt"); AddListFromFile(list, "text7.txt"); AddListFromFile(list, "text8.txt"); AddListFromFile(list, "text9.txt"); AddListFromFile(list, "text10.txt"); var sqlConnectionSb = new SQLiteConnectionStringBuilder { DataSource = DbPath }; using (var cn = new SQLiteConnection(sqlConnectionSb.ToString())) { cn.Open(); using (var cmd = new SQLiteCommand(cn)) { // テーブルをつくる cmd.CommandText = $"create table if not exists {TableName}(" + "id integer primary key autoincrement," + "first text ," + "second text ," + "third text ," + "fourth text)"; cmd.ExecuteNonQuery(); // トランザクションを使わないと恐ろしく時間がかかるので注意 cmd.Transaction = cn.BeginTransaction(); foreach (string str in list) { // データを追加 string[] vs = str.Split('\t'); string command = ""; command += $"insert into {TableName}(first, second, third, fourth) "; command += $"values('{vs[0]}', '{vs[1]}', '{vs[2]}', '{vs[3]}')"; cmd.CommandText = command; cmd.ExecuteNonQuery(); } cmd.Transaction.Commit(); } } } } |
一番上のテキストボックスに数字を入力して[表示]ボタンを押すとIDが一致するデータを取得することができます。
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 |
public partial class Form1 : Form { int GetNumberFromTextBox() { try { return int.Parse(textBoxID.Text); } catch { return -1; } } private void ButtonShowData_Click(object sender, EventArgs e) { int id = GetNumberFromTextBox(); if (id < 1) return; var sqlConnectionSb = new SQLiteConnectionStringBuilder { DataSource = DbPath }; using (var cn = new SQLiteConnection(sqlConnectionSb.ToString())) { cn.Open(); using (var cmd = new SQLiteCommand(cn)) { cmd.CommandText = $"select * from {TableName} where id == {id.ToString()}"; using (SQLiteDataReader reader = cmd.ExecuteReader()) { if (reader.Read()) { System.Collections.Specialized.NameValueCollection values = reader.GetValues(); textBoxID.Text = values[0]; textBox1.Text = values[1]; textBox2.Text = values[2]; textBox3.Text = values[3]; textBox4.Text = values[4]; } else { textBox1.Text = "NoData"; textBox2.Text = ""; textBox3.Text = ""; textBox4.Text = ""; } } } } } } |
またデータを更新したり削除する機能も追加してみました。
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 |
public partial class Form1 : Form { private void ButtonUpdate_Click(object sender, EventArgs e) { int id = GetNumberFromTextBox(); if (id < 1) return; var sqlConnectionSb = new SQLiteConnectionStringBuilder { DataSource = DbPath }; using (var cn = new SQLiteConnection(sqlConnectionSb.ToString())) { cn.Open(); using (var cmd = new SQLiteCommand(cn)) { cmd.CommandText = $"update {TableName} set first = '{textBox1.Text}' where id = {id}"; cmd.ExecuteNonQuery(); cmd.CommandText = $"update {TableName} set second = '{textBox2.Text}' where id = {id}"; cmd.ExecuteNonQuery(); cmd.CommandText = $"update {TableName} set third = '{textBox3.Text}' where id = {id}"; cmd.ExecuteNonQuery(); cmd.CommandText = $"update {TableName} set fourth = '{textBox4.Text}' where id = {id}"; cmd.ExecuteNonQuery(); } } } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
public partial class Form1 : Form { private void ButtonDelete_Click(object sender, EventArgs e) { int id = GetNumberFromTextBox(); if (id < 1) return; var sqlConnectionSb = new SQLiteConnectionStringBuilder { DataSource = DbPath }; using (var cn = new SQLiteConnection(sqlConnectionSb.ToString())) { cn.Open(); using (var cmd = new SQLiteCommand(cn)) { cmd.CommandText = $"delete from {TableName} where id = {id}"; cmd.ExecuteNonQuery(); } } } } |
上のコードではプライマリキーで検索していますが、この場合はほとんど時間はかかりません。5000万件くらい登録するとデータベースの大きさは12GB弱になりますが、プライマリキーの検索であれば一瞬で結果を返します。しかしそれ以外の検索であればけっこうな時間がかかります。
この記事を書いたあとみつけた記事なのですが、
SQLite3に60億件のデータを登録を登録できるか?という質問です。回答者も実際に1億件のデータを登録したという強者でした。