我应该关心我使用移动应用程序和网络进行的本地数据库调用的数量吗?

问题描述 投票:0回答:1

我正在构建一个具有网络支持的flutter应用程序,并使用drift作为本地存储数据库。我有一个具有以下架构的表:

CREATE TABLE Tasks(
   Id INT NOT NULL PRIMARY KEY AUTOINCREMENT,
   Name TEXT NOT NULL,
   Priority INT NOT NULL
   IsSynced BOOLEAN DEFAULT false);

是否可以进行不同的漂移异步数据库调用来获取具有不同优先级的未同步记录,或者我应该编写一个漂移查询来获取所有非同步记录并根据代码中的优先级将它们分开。我知道在这种情况下这并没有多大不同。由于漂移用于本地存储。我应该关心数据库调用的数量吗?

android flutter sqlite drift moor
1个回答
0
投票

第一

Id INT NOT NULL PRIMARY KEY AUTOINCREMENT, 

将导致错误,因为仅当列类型专门为 INTEGER 时才允许使用

AUTOINCREMENT
。你会失败,因为
AUTOINCREMENT is only allowed on an INTEGER PRIMARY KEY

第二个

如果您正在考虑效率,请考虑您是否真的需要

AUTOINCREMENT

  • AUTOINCREMENT
    令人困惑的是,实际上并不会导致生成唯一的ID,而是一个约束(规则),它强加了这样的条件:如果生成该值,则该值必须大于任何已存在的值(如果不存在) .

  • 约束/规则由附加表 sqlite_sequence 提供,每个表一行,保存有史以来分配的最高 id 值。

    • 访问和维护此表虽然是自动的,但确实会消耗额外的资源。
    • 每个表至少需要一个页面(默认 4k),因此 4k 可能可以满足该页面的一小部分
  • 请参阅 https://www.sqlite.org/autoinc.html 以获取更全面的概述,其中还提到了 rowid,如果使用 INTEGER PRIMARY KEY,则由具有该定义的列作为别名。

  • 注意第一句话。

我应该关心数据库调用的数量吗?

关于db调用次数,取决于使用场景。单个调用在不拆分的情况下会返回大量数据吗?如果是这样,单个块中的所有数据的处理效率可能会较低,与服务器通信可能成为瓶颈的多个调用相比。

您应该根据您的需求进行研究。

演示

AUTOINCREMENT
v just
INTEGER PRIMARY KEY
(以及列类型灵活性)

也许考虑以下代码(在 SQLite 工具中使用(在本例中为 Navicat for SQLite)):-

/* Just in case the environment is dirty */
DROP TABLE IF EXISTS Tasks;
DROP TABLE IF EXISTS Tasks2;
/* Create the question's table (corrected by changing INT to INTEGER) */
CREATE TABLE IF NOT EXISTS Tasks(id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, priority int NOT NULL, issynced boolean_or_whatever_due_to_column_type_flexibility DEFAULT false);
/* The comparison */
/*      NOTE without AUTOINCREMENT */
/*      NOTE demonstration of flexible column types
        i.e. a column type of the ridiculous "boolean_or_whatever_due_to_column_type_flexibility" column type
            will be given a type affinity of NUMERIC due to BOOL (see 3.1.1 of https://sqlite.org/datatype3.html)
*/
CREATE TABLE IF NOT EXISTS Tasks2(id INTEGER NOT NULL PRIMARY KEY, name TEXT NOT NULL, priority int NOT NULL, issynced boolean_or_whatever_due_to_column_type_flexibility DEFAULT false);
/* Insert base starting row for both tables */
INSERT INTO tasks VALUES(1000,'namexxx',99,1);
INSERT INTO tasks2 SELECT * FROM tasks;
/* insert another 1000 rows into tasks table */
WITH
    /* create CTE (Common Table Expression (a temporary table that exists for the duration of the execution)) 
        with 1 column, named i, that has a value 1, 2 3 ... to 1000 */
    cte_generate_many(i) AS (
        SELECT 1 /* first row */
        UNION ALL 
            SELECT 
                i+1 /* 1 greater than the current row from the cte, so ever increasing */ 
                FROM cte_generate_many 
                LIMIT 1000 /* recursively add rows till stopped (LIMIT 1000) */ 
    )
INSERT INTO tasks (name,priority,issynced)
    SELECT 
        'name'||i, /* Name will be "name?" where ? is 1 then 2 then 3 .... */
        abs(random() % 10) + 1, /* priroity will be random between 1 and 10 */
        (i % 3) > 0 
        FROM cte_generate_many
;
/* insert another 1000 rows into tasks2 table (comparison) same as previous bar into tasks2 not tasks table */
WITH
    cte_generate_many(i) AS (
        SELECT 1
        UNION ALL SELECT i+1 FROM cte_generate_many LIMIT 1000
    )
INSERT INTO tasks2 (name,priority,issynced)
    SELECT 'name'||i,
        abs(random() % 10) + 1,
        (i % 3) > 0 
        FROM cte_generate_many
;
/* show the 2 tables and then sqlite sequence */
SELECT * FROM tasks;
SELECT * FROM tasks2;
SELECT * FROM sqlite_sequence;
/* demonstrate that AUTOINCREMENT constrain is not applied if value is given (not generated) */
INSERT INTO tasks VALUES(-1000,'namezzzz',99,1);
INSERT INTO tasks2 VALUES(-1000,'namezzzz',99,1);
SELECT * FROM tasks WHERE id < 1 UNION ALL SELECT * FROM tasks2 WHERE id < 1;
/* Cleanup */
DROP TABLE IF EXISTS Tasks;
DROP TABLE IF EXISTS Tasks2;
  • 注意试图解释正在做的大部分事情的评论

以上结果有4个结果。他们是:-

结果1

至:-

结果 2(即非常相同的表,但 没有

AUTOINCREMENT

至:-

结果3

  • 即任务 2 表没有行(因此任务 2 表没有开销)

结果4

  • 即如果提供值(无论自动增量),则插入值低于最高值的行没有问题

1对2的讨论

简而言之,除了基于随机值的优先级之外,没有任何区别。因此,就 1000 行而言,自动增量与否没有什么区别。

  • 如果使用自动增量并且删除具有最高 id 的行,则下一个生成的 id 将如同该行仍然存在一样。虽然没有自动增量,下一个插入(通常)将与删除的行相同(如果删除的行是最高的 id)。

可以看到,荒谬的列名没有真正的区别(事实上,BOOLEAN 本身不是实际的列亲和类型之一,它们是 NULL、INTEGER、REAL、TEXT、BLOB 和 NUMERIC)。然而,除了 rowid 或其别名(该 id 在任务和任务2中都存在),那么列可以保存任何类型的值,这是大多数其他 RDB 不提供的功能。

当谈到 AUTOINCRMENT 时,选择这个关键字是为了让 SQLite 与其他 RDB 更加兼容。

© www.soinside.com 2019 - 2024. All rights reserved.