SQLite - 从SQLite数据库读取数据的最快方法?

时间:2012-10-03 20:37:29

标签: c# database sqlite query-optimization

我有一个本地SQLite数据库

表详情

-- Describe PREFIX_LIST
CREATE TABLE PREFIX_LIST(ITEM VARCHAR(25) PRIMARY KEY)

-- Describe SUFFIX_LIST
CREATE TABLE SUFFIX_LIST(ITEM VARCHAR(25) PRIMARY KEY)

-- Describe VALID_LIST
CREATE TABLE VALID_LIST (
    "PART1" TEXT,
    "PART2" TEXT,
    PRIMARY KEY(PART1, PART2)
)

现在这个列表非常庞大,我需要从中保存数据。

这是我的实施。

SQLiteConnection con = null;
SQLiteCommand cmd = null;
Connect(DbPath, ref con, ref cmd);

cmd.CommandText =
    "SELECT PART1 || '@' || PART2 FROM VALID_LIST 
 WHERE NOT EXISTS 
   (SELECT * FROM PREFIX_LIST WHERE VALID_LIST.PART1 LIKE '%' || ITEM || '%') 
   AND NOT EXISTS
   (SELECT * FROM SUFFIX_LIST WHERE VALID_LIST.PART2 LIKE '%' || ITEM || '%')";

var reader = cmd.ExecuteReader();

if (reader.HasRows)
{
    string savePath;

    if (SaveTextFile(out savePath) == DialogResult.OK)
    {
        TextWriter writer = new StreamWriter(savePath);
        while (reader.Read())
        {
            writer.WriteLine(reader.GetString(0));
        }
        writer.Close();
        writer.Dispose();
    }

}

reader.Close();
reader.Dispose();
cmd.Dispose();
con.Close();
con.Dispose();

MessageBox.Show("List Saved!.", Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Information);

我需要更好的方法来更快地保存列表。 VALID_LIST 中的总条目数为2639117

并且花了15分钟为上面的SQL QUERY保存它!

如果可以优化sql查询,请lmk!

提前致谢

3 个答案:

答案 0 :(得分:6)

除非通配符附加到后缀,否则LIKE的查询通常会非常慢。诸如LIKE '%foo'之类的谓词不能通过典型的字符串索引编制索引。

但是,您可以使用full text search(FTS)功能替换sqlite中繁重的LIKE用法。

  

FTS3和FTS4扩展模块允许用户创建特殊的   具有内置全文索引的表(以下称为“FTS表”)。该   全文索引允许用户有效地查询数据库   所有包含一个或多个单词的行(以下称为“标记”),即使   该表包含许多大型文档。

他们的an example在您的用例表现方面看起来很有前途。

CREATE VIRTUAL TABLE enrondata1 USING fts3(content TEXT);     /* FTS3 table */
CREATE TABLE enrondata2(content TEXT);                        /* Ordinary table *

SELECT count(*) FROM enrondata1 WHERE content MATCH 'linux';  /* 0.03 seconds */
SELECT count(*) FROM enrondata2 WHERE content LIKE '%linux%'; /* 22.5 seconds */

答案 1 :(得分:2)

考虑使用全文搜索。

要使其工作,必须对PREFIX和SUFFIX中的值进行标记化(它们必须是单独的单词),并且您尝试匹配的ITEM必须是其中一个值中的不同标记(不是一两个字或两个字)。例如,PREFIX和SUFFIX中的字符串必须是“RED BLUE GREEN”或“DOG,CAT,CAPYBARA”,而ITEM的值必须是RED,BLUE,GREEN,DOG,CAT或CAPYBARA。

如果满足这些条件,您可以启用全文搜索,将这些表重新创建为全文表,并将MATKE(和通配符)替换为MATCH。在这种情况下,SQLite将在PREFIX或SUFFIX中找到的每个标记上维护索引,并且搜索的部分将更快,更快。

不幸的是,在SQlite中启用FTS涉及从源代码编译产品,并设置一个或多个编译时标志。我没有这方面的经验。

答案 2 :(得分:0)

我不确定这是否是你想要的,但它有助于加快写入过程。尝试在字符串生成器中累积从数据库中读取的字符串,然后写入文件。 例如,您可以读取100k字符串,然后立即将100k写入文件。

    StringBuilder builder = new StringBuilder();
    int count = 0; //to limit the number of rows stored in string builder.
    while (reader.Read())
    {

        builder.AppendLine(reader.GetString(0));
        count++;

        //store every 100k or so rows at once. 
        //This number depends on how much RAM 
        //you can allocate towards storing the string of rows.
        //If you have 2GB of free RAM
        //this number can easily be 1 million but it always depends on the
        //size of each string stored in database.
        if(count == 100000) 
        {
           File.AppendAllText(path, builder.ToString()); //Append all rows to the file
           builder.Clear(); //clear the string for next 100k rows of data
           count = 0; //Clear the counter value
        }
        count++
    }

如果有帮助,请告诉我。