c#和SQLite,查询执行很慢

时间:2017-04-26 19:10:56

标签: c# sqlite

我首先说我是C#和SQL的初学者,很抱歉,如果我的代码包含一些垃圾。

我是一个日语词典的sqlite表 它有以下几行:

ID :唯一的自动增量整数; 单词:日语中的单词"表意文字" (es。:元気);
阅读:单词的语音阅读(es。:げんき);
定义:字典定义这个词;

单词可能会在字典中出现不止一次 有时可能会有多个条目,其中" word"和#34; reding"是相同的,我需要检索所有这些:

ID - 单词 - 阅读 - 定义
1 - 爱 - あい - 爱;
2 - 爱 - あい - 1800本书的标题......;

这是我检索结果的方法:

void Search(string _word, string _reading) //es.: Search(愛, あい);
{
    ...
    using(var conn = new SQLiteConnection("Data Source=dictsdb.sqlite;Version=3;"))
    {
        conn.Open();
        string sql = "SELECT * FROM dictionary WHERE word = '" + _word + "' AND reading = '" + _reading + "'";

        using(var command = new SQLiteCommand(sql, conn))
        {
            using(var reader = command.ExecuteReader(CommandBehavior.CloseConnection))
            {
                while(reader.Read())
                {
                    (...)
                }
            }
        }
    conn.Close();
    }
...
}

字典没有按特定方式排序,因此我无法使用优化的搜索算法 我无法对字典进行排序,因为我需要它的实际顺序。

缓慢的部分是command.ExecuteReader() 我想因为每次搜索都必须检查字典的所有条目,这是巨大的。

有什么建议让它更快?

编辑:谢谢大家的建议!索引技巧解决了这个问题,现在快了几倍!还要感谢其他建议,比如参数化输入!

2 个答案:

答案 0 :(得分:2)

首先,祝贺你开始了第一个C#/ SQLite项目,祝你好运。我建议稍微调整一下你的数据。例如:

1)表格结构。听起来你的单词之间存在多对一的关系 - >阅读定义。意思是,你有很多阅读可能会多次使用相同的工作。然后,您可以重构表结构以表示类似这样的内容:

   JD_Word               JD_Reading
|------------|         |------------|
|     ID     |  |----->|     ID     |
|    Word    |  |      |   Reading  |
| Reading ID |--|      |------------|
| Definition |
|------------|

2)索引。通常,创建简单索引可能是个好主意。作为概述,索引减少了数据库必须扫描的数据页数。在SQLite中,您的主键应自动编入索引。有关GetFileAttributes的更多信息。您可以在JD_Reading表上创建多列索引:

当前结构:

CREATE INDEX dictionary_word ON dictionary(word);

具有多列的当前结构

CRAETE INDEX dictionary_word ON dictionary(word, reading);

here(见第一点):

CREATE INDEX dictionary_word ON JD_Word(Word);
CREATE INDEX dictionary_reading ON JD_Reading(Reading);

3)还有很多其他选择!查看3NF突出显示一些C#/ SQLite性能问题。如果您有任何问题,请发表评论。快乐的编程。

答案 1 :(得分:1)

要加快查询速度,请在dictionary表格中添加一个索引,至少包含word列(reference):

CREATE INDEX IdxDictionary ON dictionary(word);

根据每个单词的读数数量,可能值得将性能与多列索引的性能进行比较:

CREATE INDEX IdxDictionary ON dictionary(word, reading);

多列索引占用的空间比第一列多;如果存储无关紧要,你可以创建第二个。

当我们假设_word_reading都是用户输入时,需要对它们进行参数化以防止用户入侵您的数据库:

string sql = "SELECT * FROM dictionary WHERE word=@word AND reading=@reading";

using(var command = new SQLiteCommand(sql, conn))
{
    command.Parameters.AddWithValue("@word", _word);        
    command.Parameters.AddWithValue("@reading", _reading);        

    ...
}

如果预期匹配的数量很高,您可以进一步优化:仅提取IDdefinition列,wordreading是多余的。