Nested FutureBuilder vs nested calls for lazy loading from database

故事扮演 提交于 2019-12-02 03:44:42

Given that I don't see too much code on this example, I'll do a high-level answer on your questions.

Evaluate Approach One

  1. Right off the bat this part sticks out: "returns all dep_id from Employee table"
  2. I would say scratch that, since "return all" is typically never a good solution, especially since you mention your tables have a lot of rows.

Evaluate Approach Two

  1. I'm not sure what the difference in performance this has compared to the first approach, seems also bad for the same reasons. I think this one just changes your UI logic a big is all.

Typical 'Endless' List Approach

  1. You would do a query on the Employees table with a join to the Departments table.
  2. You would implement Pagination on your UI and pass in your values to the query from step one.
  3. At a basic level you'll need these variables: Take, Skip, HasMore
  4. Take: The count # of items to request each query
  5. Skip: The count # of items to skip on the next query, this will be the size of the number of items you currently have in your List in memory driving your UI.
  6. HasMore: You can set this on the response of each query, to let the UI know if there are still more items or not.
  7. As you scroll down the list, when you get to the bottom, you will request more items .

Initially issue a query for example: Take: 10, Skip: 0 Next query when you hit the bottom of the UI: Take: 10, Skip: 10 etc..

Example sql query:

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

Hopefully, this helps, I'm not fully sure what you're trying to do actually - in terms of Code.

As far as I can tell, what you're looking to do is get a list of employees with relevant info including department.

If that's the case, then it's tailor made for INNER JOIN. Something like this:

SELECT Employee.*, Department.dep_id, Department.dep_title 
   FROM Employee INNER JOIN Department 
   ON Employee.dep_id = Department.dep_id;

(although you may want to double check that, my SQL is a bit rusty).

This would do what you need in one step. However, there is still the issue of what you're asking which seems to be "Is it more efficient to do many small requests or one big one, and what are the performance ramifications".

The answer to that is a bit specific to Flutter. What's happening when you do a request with SQFLITE, is that it is processing whatever you've passed to it, sending it to java/objc and possibly doing more processing and pushes processing to a backround thread, which then calls to the SQLITE library which does more processing to understand the request, then actually reads the data on the disk to do the operation, then returns back to the java/objc layer, which pushes the response to the UI thread, which in turns responds back to dart.

If that doesn't sound particularly efficient, that's because it isn't =D. If you're doing this a few times (or even a few hundred) it's probably fine, but if you're getting into thousands as you state it might start slowing down.

The alternative you've proposed is to do one large request. You will know better than I whether that is wise; if it's a couple thousand but only ever a couple thousand, and the data you're returning is always going to be relatively small (i.e. just a 10-20 character name and department name), then you'll have say (20+20)*2000 = 8000b = 80kb of data. Even if you assume the overhead will double that size, 160 kb of data shouldn't be enough to faze any relatively recent smartphone (after all that's much smaller than any single photo!).

Now, taking some domain specific knowledge, you could optimize this. For example, if you know the number of departments is much smaller than employees (i.e. < 100 or something), you could skip the entire issue of doing joins, and simply request all departments before this begins and put it in a map (dep_id => dep_title), and then once you've requested employees you could just simply do that lookup from dep_id to dep_title yourself. That way your requests wouldn't have to include the dep_title over and over again.

That being said, you may want to consider paging the employee lookup whether or not you use a join. You'd do this by requesting 100 employees (or whatever number) at a time rather than the entire batch - that way you don't have the overhead of 1000+ calls through the stack, but you also don't have a large block of data all in memory all at once.

SELECT * FROM Employee
WHERE employee_name >= LastValue
ORDER BY employee_name
LIMIT 100;

Unfortunately that doesn't fit in as well with how flutter does lists, so you'd probably need to have something like a 'EmployeeDatabaseManager' that does the actual requests, and your list would call into it to get the data. That's probably beyond the scope of this question though.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!