我需要在可以遵循的两种方法之间选择最佳方法。
我有一个Flutter应用程序,它使用sqflite
保存数据,在数据库内部,我有两个表:
员工:
+-------------+-----------------+------+
| employee_id | employee_name |dep_id|
+-------------+-----------------+------+
| e12 | Ada Lovelace | dep1 |
+-------------+-----------------+------+
| e22 | Albert Einstein | dep2 |
+-------------+-----------------+------+
| e82 | Grace Hopper | dep3 |
+-------------+-----------------+------+
SQL:
CREATE TABLE Employee(
employee_id TEXT NOT NULL PRIMARY KEY,
employee_name TEXT NOT NULL ,
dep_id TEXT,
FOREIGN KEY(dep_id) REFERENCES Department(dep_id)
ON DELETE SET NULL
);
部门:
+--------+-----------+-------+
| dep_id | dep_title |dep_num|
+--------+-----------+-------+
| dep1 | Math | dep1 |
+--------+-----------+-------+
| dep2 | Physics | dep2 |
+--------+-----------+-------+
| dep3 | Computer | dep3 |
+--------+-----------+-------+
SQL:
CREATE TABLE Department(
dep_id TEXT NOT NULL PRIMARY KEY,
dep_title TEXT NOT NULL ,
dep_num INTEGER,
);
我需要显示存储在 Employee 表中的ListGrid
个部门。我应该查看 Employee 表并从中获取部门ID,这很容易,但是在获取dep_id
之后,我需要用这些ID制作卡,因此我需要来自部门的信息表。
我从 Emplyee 表中获取的那些ID的完整信息位于部门表中。
每个表中都有数千行。
我有一个数据库助手类可以连接到数据库:
DbHelper
是这样的:
Future<List<String>> getDepartmentIds() async{
'fetch all dep_id from Employee table'
}
Future<Department> getDepartment(String id) async{
'fetch Department from Department table for a specific id'
}
Future<List<Department>> getEmployeeDepartments() async{
'''1.fetch all dep_id from Employee table
2.for each id fetch Department records from Department table'''
var ids = await getDepartmentIds();
List<Departments> deps=[];
ids.forEach((map) async {
deps.add(await getDepartment(map['dep_id']));
});
}
有两种方法:
在dbhelper中定义一个函数,该函数返回 Employee 表中的所有dep_id
(getDepartmentIds
),另一个函数返回该特定ID的部门对象(模型) 。(getDepartment
现在我彼此之间需要两个FutureBuilder
,一个用于获取ID,另一个用于获取部门模型。
getEmployeeDepartments
)FutureBuilder
。哪个更好??
我应该让FutureBuilders处理该问题还是应该向dbHelper
施加压力以使其陷入困境?
如果我使用第一种方法,则(据我所能想象!)必须放置第二个以后的调用(该调用基于其id获取部门对象(模型)的调用) getDepartment
函数上的build
)),建议不要这样做。
第二个问题是它在dbHelper
中进行了很多嵌套调用。
我使用ListView.builder
来提高性能。
我检查了一些数据,但无法弄清楚哪个更好。我猜这取决于flutter和sqlite(sqflite)。
哪个更好或更有效?
答案 0 :(得分:2)
鉴于在此示例中我看不到太多代码,因此我将对您的问题做一个高级答复。
评估方法一
评估方法二
典型的“无尽”列表方法
最初发出一个查询,例如:取:10,跳过:0 到达用户界面底部时的下一个查询:接受:10,跳过:10 等。
示例SQL查询:
SELECT *
FROM Employees E
JOIN Departments D on D.id = E.dept_id
order by E.employee_name
offset {SKIP#} rows
FETCH NEXT {TAKE#} rows only
希望这会有所帮助,根据代码方面,我不确定您实际上要做什么。
答案 1 :(得分:1)
据我所知,您想要做的是获取具有相关信息(包括部门)的员工列表。
如果是这种情况,那么它是为INNER JOIN量身定制的。像这样:
SELECT Employee.*, Department.dep_id, Department.dep_title
FROM Employee INNER JOIN Department
ON Employee.dep_id = Department.dep_id;
(尽管您可能要仔细检查一下,但我的SQL有点生锈)。
这将一步完成您需要的工作。但是,仍然存在您要问的问题,这似乎是“执行许多小请求或一个大请求是否更有效,以及对性能的影响是什么”。
答案是Flutter特有的。当您使用SQFLITE进行请求时,发生的事情是它正在处理传递给它的任何内容,将其发送到java / objc并可能进行更多处理,并将处理推送到backround线程,然后该线程调用SQLITE库,进行更多处理以了解请求,然后实际读取磁盘上的数据以执行操作,然后返回到java / objc层,该层将响应推送到UI线程,而UI线程又将响应返回给dart。>
如果这听起来不是特别有效,那是因为它不是= D。如果您进行几次(甚至几百次),可能没问题,但是如果您陈述的次数成千上万次,它可能会开始变慢。
您建议的替代方法是提出一个大要求。您会比我更清楚这是否明智;如果是几千,但只有几千,并且您返回的数据总是相对较小(例如,只有10-20个字符的名称和部门名称),那么您会说(20 + 20 )* 2000 = 8000b = 80kb的数据。即使您认为开销将是该大小的两倍,160 kb的数据也不足以使任何相对较新的智能手机(毕竟比任何一张照片都要小!)。
现在,借助一些特定领域的知识,您可以对其进行优化。例如,如果您知道部门的数量比雇员少得多(即<100左右),则可以跳过整个加入联接的过程,只需在开始之前请求所有部门并将其放入地图中(dep_id = > dep_title),然后一旦您请求了员工,您就可以自己从dep_id到dep_title进行查找。这样,您的请求将不必一遍又一遍地包含dep_title。
话虽如此,无论您是否使用联接,您都可能要考虑分页雇员查找。为此,您可以一次请求100名员工(或任意数量),而不是整个批次-这样一来,您就不会有超过1000个呼叫遍历整个堆栈的开销,但是您也没有很大的块一次将所有数据全部存储在内存中。
SELECT * FROM Employee
WHERE employee_name >= LastValue
ORDER BY employee_name
LIMIT 100;
不幸的是,这与Flutter进行列表的方式不太一样,因此您可能需要像'EmployeeDatabaseManager'这样的东西来执行实际的请求,并且您的列表会调用它来获取数据。但这可能超出了这个问题的范围。