SQLite查询性能:更新与加入

SQLite查询性能:更新与加入,sql,sqlite,Sql,Sqlite,我已经为此奋斗了几个星期了——正如你所看到的和所看到的。虽然我在那里得到的答案是正确的,但由于性能问题,它们不适合我。下面是更多 我正在使用SQLite。我有一个表,其中的行表示某个时间点中的个人。我正在尝试使用另一列status的滞后值创建列statusLag,如下所示: workerID timeVar status statusLag --------------------------------------------- 1 1

我已经为此奋斗了几个星期了——正如你所看到的和所看到的。虽然我在那里得到的答案是正确的,但由于性能问题,它们不适合我。下面是更多

我正在使用SQLite。我有一个表,其中的行表示某个时间点中的个人。我正在尝试使用另一列status的滞后值创建列statusLag,如下所示:

workerID    timeVar     status      statusLag
---------------------------------------------
1           1           0           NULL
1           2           1           0
1           3           1           1
1           4           1           1
----------------------------------------------
2           3           1           NULL
2           4           0           1
2           5           1           0
2           6           0           1
我试过的 方法1:更新 我不清楚这是否会起作用。此外,这是我第一次加入,我的印象是,仅此查询不会在myTable上插入或更新任何内容。我需要补充这个查询来完成我在文章开头解释的内容吗


任何想法,任何帮助,非常感谢。我已经为此苦苦挣扎了两周,我需要完成这项工作。

如果要更改表中的值,则需要使用update、insert或delete

如果这是您的查询:

UPDATE myTable
    SET statusLag = (SELECT t2.status
                     FROM myTable t2
                     WHERE t2.workerID = myTable.workerID AND
                           t2.timeVar < myTable.timeVar
                     ORDER BY t2.timeVar desc
                     LIMIT 1
                    );
然后您可能有机会使用myTableworkerId、timeVar和status上的索引。但是,老实说,对于32亿行和16GB的RAM,这可能仍然没有帮助


几乎任何其他数据库都有可能帮助MySQL中变量滞后的结构。是否有可能使用另一个数据库?

您可以尝试的一种策略是将其分解为多个较小的更新

也就是说,您不会试图一次更新32亿行。找到一种方法,把它分成30组,每组1亿行,一次一组

这有几个缺点:

在一段时间内,您将更新一些行,而一些行未更新。 你必须想办法把它们分成可用的块。 但最大的优势是它最终可能会起作用

比如:

UPDATE myTable
    SET statusLag = (SELECT t2.status
                     FROM myTable t2
                     WHERE t2.workerID = myTable.workerID AND
                           t2.timeVar < myTable.timeVar
                     ORDER BY t2.timeVar desc
                     LIMIT 1
                    )
     WHERE companyID = 1;
并为数据库中的每个companyID运行它

等等

重要的是让数据库进行更新,并在移动到下一组要更新的记录之前完成事务。如果您试图将其全部打包到一个事务中,那么您将遇到同样的问题,即必须在动态更新中管理32亿行的更新

您可能希望自动更新,例如编写一些java或其他东西来循环公司ID,或者您可以简单地使用体面的文本编辑器创建30或40条SQL语句,然后手动运行它们


如果您需要维护此数据,那么我建议您在创建行时包含滞后数据-一次一个比这样的大批量容易得多。

更新操作很慢,因为数据库引擎必须获取行,运行子查询以获取新值,然后将行存储到位。有时它不适合它所在的位置,必须放在仓库的其他地方

为了获得更好的性能,我希望这样做:

使用statusLag列创建一个表myLagTable 运行一个INSERT,请参见下文 将myTable重命名为myOldTable 将myLagTable重命名为myTable 这样,myTable在重命名操作期间不可用

要填充myLagTable,可以使用连接:

请注意,我删除了ORDER BY,因为在INSERT中不需要它,它将使用Resources CPU、内存和磁盘对行进行排序


一旦您对结果感到满意,您可以删除myOldTable

当我有时间投资建立一个数据库时,将有机会使用另一个数据库。加入是一个糟糕的解决方案吗?@djas。join可以,但不会更改数据。
UPDATE myTable
    SET statusLag = (SELECT t2.status
                     FROM myTable t2
                     WHERE t2.workerID = myTable.workerID AND
                           t2.timeVar < myTable.timeVar
                     ORDER BY t2.timeVar desc
                     LIMIT 1
                    );
UPDATE myTable
    SET statusLag = (SELECT t2.status
                     FROM myTable t2
                     WHERE t2.workerID = myTable.workerID AND
                           t2.timeVar < myTable.timeVar
                     ORDER BY t2.timeVar desc
                     LIMIT 1
                    )
     WHERE companyID = 1;
     WHERE companyID =>  0 AND companyID < 1000;
INSERT INTO myLagTable(workerID, timeVar, status, statusLag)
SELECT t1.*, t2.status as statusLag 
FROM myTable AS t1
LEFT JOIN myTable AS t2
ON t1.workerID=t2.workerID AND t1.timeVar=t2.timeVar+1;