我正在使用pi将视频监控数据记录在每个摄像头的单个但人口密集的桌子中。该表由3列组成 - 时间戳,偏移量和帧长度。视频数据存储在文件系统上的单独文件中。我的代码是用C语言编写的。
时间戳是流中视频帧的日期/时间,offset是流数据文件中的fseek / ftell偏移量,帧长度是帧的长度。非常自我解释。主索引和唯一索引位于时间戳列上。
每个摄像头有一个数据库写入器分叉进程,并且可能有多个分叉的只读进程随时查询数据库。
这些进程由经典客户端/服务器体系结构中的套接字侦听器创建,该体系结构接受来自管理监视摄像机和查询它的客户端的其他进程的视频流。
当只读客户端连接时,它会为所选摄像机选择数据库中的第一行。出于某种原因,选择>在相同查询上60秒和后续选择是非常快速的(远小于1秒)。我调试了代码以确定这是原因。
我已经为阅读器和编写器分叉进程配置了这些pragma,并尝试了更大和更小的值,只要有最小的影响:
pragma busy_timeout=7000
pragma cache_size=-4096
pragma mmap_size=4194304
我假设原因是由于在只读客户端连接时填充SQLite3缓存,但我不确定还有什么可以尝试。
我已经实现了自己的写入缓存/缓冲策略来帮助防止锁定,这有很大帮助,但它并没有解决启动时的延迟问题。
我还在工作日之前将表格拆分,以帮助控制表格的人口规模。一旦人口接近10万行,问题就开始发生了。每桌的人口约为250万行。
以下是查询:
sprintf(sql, "select * from %s_%s.VIDEO_FRAME where TIME_STAMP = "
"(select min(TIME_STAMP) from %s_%s.VIDEO_FRAME)",
cam_name, day_of_week, cam_name, day_of_week);
(编辑)
$ uname -a
Linux raspberrypi3 4.1.19-v7+ #858 SMP Tue Mar 15 15:56:00 GMT 2016 armv7l GNU/Linux
$ sqlite3
sqlite> .open Video_Camera_02__Belkin_NetCam__WED.db
sqlite> .tables VIDEO_FRAME
sqlite> .schema VIDEO_FRAME CREATE TABLE VIDEO_FRAME(TIME_STAMP UNSIGNED BIG INT NOT NULL,FRAME_OFFSET BIGINT, FRAME_LENGTH INTEGER,PRIMARY KEY(TIME_STAMP));
sqlite> explain query plan
...> select * from VIDEO_FRAME where TIME_STAMP = (select min(TIME_STAMP) from VIDEO_FRAME);
0|0|0|SEARCH TABLE VIDEO_FRAME USING INDEX sqlite_autoindex_VIDEO_FRAME_1 (TIME_STAMP=?)
0|0|0|EXECUTE SCALAR SUBQUERY 1 1|0|0|SEARCH TABLE VIDEO_FRAME USING COVERING INDEX sqlite_autoindex_VIDEO_FRAME_1 –
经过一些进一步的故障排除后,罪魁祸首似乎是分叉数据库编写器进程。我尝试启动r / o客户端,没有写入流数据,并立即返回选择。我没有找到根本问题,但至少已经隔离了它的来源。
谢谢!