1

我正在使用 Windows Azure 表存储来存储数百万个实体,但是我试图找出可以轻松实现两件事的最佳解决方案:

1)对实体的搜索,将检索该实体以及该实体任一侧的至少(pageSize)个实体

2) 如果实体两侧的实体数量超过 (pageSize) 个实体,则显示下一页或上一页链接,这将持续到开始或结束。

3) 顺序是逆时间顺序

我决定 PartitionKey 将是用户提供的 Title,因为每个容器在系统中都是唯一的。RowKey 是 Steve Marx 的词典算法:

http://blog.smarx.com/posts/using-numbers-as-keys-in-windows-azure

当转换为 javascript 而不是 c# 时,它看起来像这样:

垫(新日期(100000000 * 86400000).getTime()-新日期().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。

任何人都可以看到这种方法的陷阱或问题吗?

4

1 回答 1

1

我看不出这如何有效和高效地工作,尤其是在获取前一页的行时。

为了提高效率,“key”的前缀需要是一个连续递增或递减的值,而不是基于时间戳。时间戳生成的值会有重复和漏洞,这使得将页面大小映射到行数在最好的情况下效率低下,在最坏的情况下难以确定。

此外,这种潜在的算法依赖于单个分区键,从而破坏了表的可伸缩性。

这里的挑战是有一种方法来生成一个连续递增的密钥。一种解决方案是使用 SQL 数据库并对单行执行原子更新,以便按顺序生成递增或递减值。类似于 UPDATE ... SET X = X + 1 并返回 X。也许使用存储过程。

所以密钥可能是一个零左填充的串行生成的数字。拆分使得数字的前 N ​​位是分区键,其余 M 位是行键。

For example 
PKey    RKey
00001   10321
00001   10322
….
00954   98912

现在,由于行是按顺序排列的,因此可以使用页面大小的确切键范围编写查询。

警告。在生成序列密钥和写入表存储之间发生故障的风险很小。在这种情况下,桌子上可能会有孔。但是,您的分页算法应该能够通过指定略大于所需的页面大小或通过调整范围重试来轻松检测和解决此类实例。

于 2012-05-19T07:26:45.917 回答