我正在使用Windows Azure表存储来存储数百万个实体,但是我正在尝试找出最容易实现两件事的最佳解决方案:
1)对实体进行搜索,将检索该实体和至少(pageSize)该实体任一侧的实体数量
2)如果超出(pageSize)该实体任一侧的实体数量以外的实体,则显示下一页或下一页链接,这将继续,直到达到开始或结束。
3)顺序是反向时间顺序
我已经确定PartitionKey将是用户提供的Title,因为每个容器在系统中都是唯一的。 RowKey是Steve Marx的lexiographical算法:
http://blog.smarx.com/posts/using-numbers-as-keys-in-windows-azure
当转换为javascript而不是c#时,如下所示:
pad(new Date(100000000 * 86400000).getTime() - new Date()。getTime(),19)+“_”+ uuid()
uuid()是一个javascript函数,返回一个guid,pad最多可以添加19个字符的零。所以系统中的记录看起来像这样:
PK RK
TEST 0008638662595845431_ecf134e4-b10d-47e8-91f2-4de9c4d64388
TEST 0008638662595845432_ae7bb505-8594-43bc-80b7-6bd34bb9541b
TEST 0008638662595845433_d527d215-03a5-4e46-8a54-10027b8e23f8
TEST 0008638662595845434_a2ebc3f4-67fe-43e2-becd-eaa41a4132e2
此模式允许插入的每个新实体位于列表顶部,满足上述第3点。
有一种很好的方法在系统中添加新记录我认为然后我会创建一个机制来查看RowKey的前半部分,即0008638662595845431_部分并根据已经的方向进行大于或小于比较找到的项目。换句话说,为了在0008638662595845431之前获得该行,我会像这样进行查询:
var tableService = azure.createTableService();
var minPossibleDateTimeNumber = pad(new Date(-100000000*86400000).getTime() - new Date().getTime(), 19);
tableService.getTable('testTable', function (error) {
if (error === null) {
var query = azure.TableQuery
.select()
.from('testTable')
.where('PartitionKey eq ?', 'TEST')
.and('RowKey gt ?', minPossibleDateTimeNumber + '_')
.and('RowKey lt ?', '0008638662595845431_')
.and('Deleted eq ?', 'false');
如果返回的结果大于1000并且azure给了我一个延续令牌,那么我想我会记住最后一项RowKey即数字部分0008638662595845431。所以现在下一个查询将记住的值作为起始值等
我使用的是Windows Azure Node.Js SDK,语言是javascript。
有人能看到这种方法的问题吗?
答案 0 :(得分:1)
我没有看到它如何有效地工作,尤其是获取前一页的行。
为了提高效率,“密钥”的前缀需要是一个连续递增或递减的值,而不是基于时间戳。时间戳生成的值会有重复项和漏洞,这使得映射页面大小最好无效,最不容易确定。
此外,这种潜在的算法依赖于单个分区密钥,破坏了表的可伸缩性。
这里的挑战是有一种生成串行增量密钥的方法。一种解决方案是使用SQL数据库并对单行执行原子更新,以便按顺序生成递增或递减值。像UPDATE ... SET X = X + 1并返回X.可能使用存储过程。
因此密钥可以是零左填充的串行生成的数字。分割使得数字的前N个数字是分区键,剩余的M个数字是行键。
For example
PKey RKey
00001 10321
00001 10322
….
00954 98912
现在,由于行是按顺序排列的,因此可以编写一个具有页面大小的确切键范围的查询。
买者。生成串行密钥和写入表存储之间发生故障的风险很小。在这种情况下,表中可能有漏洞。但是,您的分页算法应该能够通过指定略大于必要的页面大小或通过重新调整范围来非常轻松地检测和解决此类实例。