我正在扫描SQLite数据库,查找所有匹配项并使用
OneFound:=False;
if tbl1.FieldByName('Name').AsString = 'jones' then
begin
OneFound:=True;
tbl1.Next;
end;
if OneFound then // Do something
或者我应该使用
if not(OneFound) then OneFound:=True;
将OneFound分配给“True”是否更快,无论分配了多少次,或者我应该进行比较并且只是第一次更改OneFuond?
我知道更好的方法是使用FTS3,但是现在我必须扫描数据库,问题更多的是关于设置OneFound的方法,因为遇到匹配或使用比较方法和设置它只是一次。
由于
答案 0 :(得分:4)
你的问题是,更快:
if not(OneFound) then OneFound:=True;
或
OneFound := True;
答案可能是第二个更快。条件语句涉及分支,这可能会导致分支错误预测。
然而,与周围的代码相比,这行代码是微不足道的。一次一行地运行数据库将是非常昂贵的。我敢打赌,你将无法衡量两个选项之间的差异,因为那个小Boolean
的处理只是被其余的代码所淹没。在这种情况下,选择更易读和更简单的版本。
但是,如果您关心此代码的性能,您应该要求数据库完成工作,就像您自己所说的那样。写一个查询来执行工作。
答案 1 :(得分:3)
最好更改SQL语句,以便在数据库中完成工作。如果你想知道在'name'字段中是否有一个包含值'jones'的元组,那么更快的查询将是
with tquery.create (nil) do
begin
sql.add ('select name from tbl1 where name = :p1 limit 1');
sql.params[0].asstring:= 'jones';
open;
onefound:= not isempty;
close;
free
end;
关于'limit'子句,你的语法可能有所不同,但想法是从数据库中只返回一个元组,它与'where'语句匹配 - 无论哪一个都无关紧要。
我使用了一个参数来避免分隔值的问题。
答案 2 :(得分:0)
<强> 1。搜索一个字段
如果要搜索一个特定的字段内容,使用INDEX和SELECT将是最快的。
SELECT * FROM MYTABLE WHERE NAME='Jones';
不要忘记先在列上创建一个INDEX!
<强> 2。快速阅读
但是如果你想在字段中搜索,或者在几个字段中搜索,你可能需要阅读并检查整个内容。在这种情况下,对于每个数据行,调用FieldByName()
的速度会很慢:最好使用本地TField
变量。
或者忘记TDataSet
,然后切换到直接访问SQLite3。事实上,使用DB.pas
和TDataSet
需要大量数据编组,因此比直接访问要慢。
参见例如DiSQLite3或我们的DB classes,它们非常快,但有点高级。或者您可以在这些类之上使用我们的ORM。我们的类能够read more than 500,000 rows per second from a SQLite3 database,包括JSON编组到对象字段中。
第3。 FTS3 / FTS4 强>
但是,正如您所猜测的那样,最快的确是使用FTS3/FTS4 feature of SQlite3。
您可以将FTS4 / FTS4视为所提供的文本blob上的“元索引”或“全文索引”。就像谷歌能够在数百万个网页中找到一个词:它不使用常规数据库,而是使用full-text indexing。
简而言之,您在数据库中创建了一个虚拟FTS3 / FTS4表,然后在此表中插入FTS TEXT字段中主记录的全文,强制ID字段为原始数据行之一
然后,您将在FTS3 / FTS4表上查询一些单词,这将为您提供匹配的ID,比常规扫描快得多。
请注意,我们的ORM有专门的TSQLRecordFTS3
/ TSQLRecordFTS4
类用于直接FTS流程。