2014-05-03 167 views
4

请有人对分页表中的记录有任何想法。其实我想用DynamoDb在php中创建一个分页组件。使用AWS分页AWS DynamoDB使用PHP

现在看来似乎是不可能给分页像<第一> <分组> 1,2,3,,5 ... <下一个> <最后>。

因为Dyanmodb只是给我们提供LIMIT条款,我们可以通过它来读取某些没有。的记录,我们可以通过LastEvaluatedKey处理下n个记录。所以如果我想直接跳到第5页,它可能怎么样?

根据我的理解,我们无法在分页中显示页码。我们可以做的只是读取记录的某些限制,并提供NEXT链接来检索下一个n记录。

分页是任何Web应用程序的基本特征,如果迁移到DynamoDb等云数据库,我们如何实现分页?

请提供您的意见和建议。谢谢

回答

0

是的,您是对的,DynamoDB中没有OFFSET。但只使用LimitLastEvaluatedKey,我做了这个功能:

public function scan($table, $filter = [], $select = null, $limit = 2) 
{ 
    $page = isset($_GET['page']) ? $_GET['page'] : 0; 
    $options = [ 
     'TableName' => $table, 
     'Count' => true, 
    ]; 

    if (!empty($limit)) { 
     $options['Limit'] = $limit; 
    } 

    if (!is_null($select)) { 
     $options['Select'] = $select; 
    } 

    if (!empty($filter)) { 
     $options['ScanFilter'] = $filter; 
    } 

    $results = $results = $this->_client->scan($options); 

    while ($page > 0 && isset($results['LastEvaluatedKey'])) { 
     $results = $results = $this->_client->scan($options); 
     $options['ExclusiveStartKey'] = $results['LastEvaluatedKey']; 
     $page--; 
    } 

    return $results; 
} 

$this->_client指DynamoDb客户对象。
基本上我通过LastEvaluatedKey循环所有条目,直到我到达需要的页面。
要获得表中的总条目,请拨打$this->scan($this->tableName(), [], null, null)['Count'];(即 - 没有任何搜索条件和没有分页,就像在正常分页功能中一样)。

+1

这样,没有大量缓存,对于性能来说会非常糟糕任何其他页面然后头几个 –

+0

@MikeDinescu是的,我知道。有更好的解决方案 – Justinas

+0

不,不是真的;我并不是说有一个更好的解决方案,只是在那里发出警告;我能想到的唯一改进就是确保缓存结果(或者至少是LastEvaluatedKey,这样后续调用不会受到每次扫描的惩罚) –

0

要添加到@Justinas的答案,迪纳摩将有非常可怕的分页性能,如果随机访问(即跳转到任意页)是所需的。但是,如果只执行下一页和上一页,则可以传递LastEvaluatedKey,并将由于扫描造成的开销降至最低。

正如评论中所述,您应该尽可能地缓存结果。至少,可以缓存LastEvaluatedKey结果,以便在用户翻阅结果时不需要为每个分页请求重新计算结果。这里是我的意思的一个例子:

假设你有一个表格,像这样的模式,其中CommentID是散列键。

CommentID | Author | Comment | ... 
-----------+--------+---------+------------ 
    1  | Joe | Foo  | ... 
    2  | Joe | Bar  | ... 
    3  | John | Baz  | ... 
    4  | Joe | FooBar | ... 
    5  | Jane | BooBaz | ... 
    6  | Joesie | Blah | ... 
    7  | Johnny | Blahaha | ... 

当您启动传呼,说你要求每页3条评论,你会得到第一页的结果和LastEvaluatedKey = 3;然后,如果您再次发出扫描请求,请使用ExclusiveStartKey=3进行第2页扫描,您将获得LastEvaluatedKey = 6;要获得第3页,您可以使用LastEvaluatedKey = 6 ..等进行另一次扫描。

您可以看到,如果没有任何形式的缓存,您将执行三次扫描(如果您在第3页之前还请求了第1页和第2页,则会重复其中的两次)。所以,我提出的优化是为每个页面存储相应的键。你会最终得到这样的地图:

Page | Hash-Key 
------+---------- 
    1 | null 
    2 |  3 
    3 |  6 
    .. | ... 

而当你翻页结果时,这些值将被填写。现在,当用户想要第3页时,您只需执行一次扫描,使用6作为ExclusiveStartKey

当然,对于每个页面大小,您都需要一个像这样的查找表,并且只有在新行被添加(或删除)之前,表才会准确无误。也就是说,如果你有很多请求,存储分页缓存所需的额外内存将非常值得。剩下的就是为你的分页缓存设置一个合理的到期时间,这取决于你的表中新增数据的频率(或删除)。

+0

如果评论被删除,您现在必须更新很多分页索引号码键,而不是一个好的解决方案所有。我相信删除将是一个主要要求。 – Ouroboros

+0

@ P.Prasad - 不确定你的意思,但通常当你对结果进行分页时,你希望通过什么样的快照进行分页 - 删除,就像插入会反映在后续分页的结果中最终要求;取决于删除和插入的频率,您可以调整缓存的TTL,甚至使缓存无效 –

+0

如果项目编号4,5,6被删除,则页面密钥映射中从页面2开始的所有条目都必须是进行修改,使其值增加3.此操作本身是资源密集型的。 – Ouroboros