在SQLite中使用随机ROWID有什么弊端?

时间:2019-01-16 09:25:05

标签: sqlite random rowid

我打算为每个新行实现一个随机的rowid,而不是默认的顺序rowid。我正在做一个Web项目,但我不想向公众公开行数。我考虑过几种提供隐私的方法,例如生成随机字符串作为UNIQUE密钥,并在将rowid发送给访问者之前使用简单的整数加密。

但是,我希望答案是关于使用随机的rowid来代替。我计划为所有具有rowid = MAX_ROWID的表插入一个虚拟行,以便插入到表中的每个新行将获得随机的rowid,这是SQLite3中记录的行为。

谢谢!

2 个答案:

答案 0 :(得分:1)

主要缺点是随机并不意味着唯一。如果您使用随机的rowID,则必须检查每个附加行的ID是否与任何先前存在的行的ID不匹配,如果匹配,则获取一个新的ID。如果您有很多行,两次获得相同ID的机会就更大,这将需要您重新计算一个随机数。

可能的解决方案:您说过要向公众隐藏行数。如果这是唯一的问题,则可以将第一行的ID随机化,然后使另一行的ID保持顺序。这样就无法知道有多少行。如果用户在特定情况下获得了所有行,他当然将能够对行进行计数并知道行数,但是没有对行ID进行随机化将帮助您解决此问题。

答案 1 :(得分:1)

一种潜在的解决方案是利用sqlite用于确定下一个rowid的算法。

通常,rowid将比前一个大1,直到获得最大值为止,然后只要 AUTOINCREMENT没有编码,SQLite就会尝试查找未使用/可用的值。

因此,如果您插入具有该值的行,则随后的行将不会是连续的。

  

如果在插入项上未指定ROWID,或者指定的ROWID具有   如果值为NULL,则会自动创建适当的ROWID。   常用的算法是为新创建的行赋予ROWID   比插入之前表中的最大ROWID大1。如果   该表最初为空,然后使用ROWID 1。如果   最大ROWID等于最大可能整数   (9223372036854775807)然后数据库引擎开始选择正数   随机选择候选ROWID,直到找到以前没有的   用过的。如果经过合理数量的操作后找不到未使用的ROWID,   尝试时,插入操作失败,并显示SQLITE_FULL错误。如果不   显式插入ROWID负值,然后自动插入   生成的ROWID值将始终大于零。SQLite Autoincrement

例如,考虑以下内容:-

DROP TABLE IF EXISTS randid;
CREATE TABLE IF NOT EXISTS randid (ID INTEGER PRIMARY KEY , data TEXT);

-- INSERT A ROW using the highest possible value for the ID 
INSERT INTO randid VALUES(9223372036854775807,'dummy'); -- <<<<<<<<<< THE BASIS OF THIS METHODOLOGY

-- insert some more data letting SQLite generate the ID
INSERT INTO randid (data) VALUES('a'),('b'),('c'),('d'),('a'),('b'),('c'),('d'),('a'),('b'),('c'),('d'),('a'),('b'),('c'),('d');

-- get the resultant data from the table
SELECT * FROM randid; 

第一次运行的结果:-

enter image description here

另一次运行的结果:-

enter image description here

除了最后一行(这是第一行添加的)之外,您甚至无法轻松确定插入顺序。

  

在SQLite中使用随机rowid有什么弊端?

我不相信使用上述方法会产生明显的影响,也许会产生少量的额外时间,然后尝试使用随机数,因为免费数越少,随机数就会变得越长(可能值得使用-9223372036854775808添加第二个初始行,这将打开负数的使用,从而使更多值可用)。但是,由于我相信分布式插入可以使B树(索引)更有效,因此也可能会有所收获。

您提到 rowid ,上面使用的是 rowid 的别名,尽管没有像 rowid 那样隐藏,但该值的意义不大如果它变得可见(为什么?(那是夸夸其谈))。

但是 rowid 的一个缺点,最初可能以相同的方式使用,是如果rowid为VACUUM,则会为所有rowid重新编号列没有别名,它将消除随机性。