我正在开发一个SQLite磁贴缓存数据库(类似于MBTiles
规范),现在只包含一个表Tiles
,其中包含以下列:
X [INTEGER]
- 水平瓦片索引(不是地图坐标)
Y [INTEGER]
- 垂直图块索引(不是地图坐标)
Z [INTEGER]
- 缩放图块的级别
Data [BLOB]
- 带有图块图像数据的流(目前是PNG图像)
所有用于平铺计算的坐标都在应用程序中完成,因此SQLite R*Tree Module
和相应的TADSQLiteRTree
类对我没有意义。我需要的是尽可能快地加载由给定Data
值找到的记录的X, Y, Z
字段blob流。
除了这个数据库之外,应用程序还有一个由这个TTileCache
类型的哈希表实现的内存缓存:
type
TTileIdent = record
X: Integer;
Y: Integer;
Z: Integer;
end;
TTileData = TMemoryStream;
TTileCache = TDictionary<TTileIdent, TTileData>;
在计算X, Y, Z
值时要求某个磁贴的工作流程很简单。我将要求一个瓦片内存缓存(部分填充在app。启动时的上表),如果在那里找不到瓦片,请询问数据库(即使找不到瓦片,下载它来自磁贴服务器)。
你会使用哪个AnyDAC(FireDAC)组件来频繁查询SQLite表中的3个整数列值(假设是100k记录),并且可以加载找到的blob流?
你会使用:
答案 0 :(得分:3)
绝对使用TADQuery
。除非您将查询设置为Unidirectional
,否则它将缓冲从内存中数据库返回的所有记录(默认值为50)。由于您正在处理blob,因此应编写查询以检索所需的最少记录数。
使用参数化查询,如下面的查询
SELECT * FROM ATable
WHERE X = :X AND Y = :Y AND Z = :Z
最初打开查询后,您可以更改参数,然后使用Refresh
方法检索下一条记录。
内存表不能用于从数据库中检索数据,它必须通过查询填充。它可以用来替换你的TTileCache
记录,但我不推荐它,因为它会比你的内存缓存实现更多的开销。
答案 1 :(得分:0)
我会将TFDQuery与以下查询一起使用。假设您要在地图上显示获取的图块,您可以考虑一次性获取缺失(非缓存)图块区域的所有图块,而不是逐个为图块网格提取图块:
SELECT
X,
Y,
Data
FROM
Tiles
WHERE
(X BETWEEN :HorzMin AND :HorzMax) AND
(Y BETWEEN :VertMin AND :VertMax) AND
(Z = :Zoom)
对于上述查询,我会考虑从fiBlobs中排除FetchOptions,以便在用户从结果集中读取切片时移动地图视图时保存一些I / O时间请求的区域超出了可见视图(您停止阅读并且从不阅读其余区域)。