6

我有一个本地 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

为上面的 SQL QUERY 保存了 15 分钟!

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

提前致谢

4

3 回答 3

6

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

但是,您可以LIKE使用其全文搜索(FTS) 功能替换 sqlite 中的大量使用。

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

他们有一个示例,在您的用例的性能方面看起来很有希望。

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 */
于 2012-10-03T21:05:20.877 回答
2

考虑使用全文搜索。

为此,必须对 PREFIX 和 SUFFIX 中的值进行标记(它们必须是单独的单词),并且您尝试匹配的 ITEM 必须是这些值之一中的不同标记(不是单词的一部分或两个字在一起)。例如,PREFIX 和 SUFFIX 中的字符串必须是“RED BLUE GREEN”或“DOG, CAT, CAPYBARA”,并且 ITEM 的值必须是 RED、BLUE、GREEN、DOG、CAT 或 CAPYBARA。

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

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

于 2012-10-03T21:07:41.923 回答
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++
    }

让我知道它是否有帮助。

于 2016-04-29T18:06:28.590 回答