根据事件日期查找日期范围的算法

发布于 2024-08-02 07:38:21 字数 491 浏览 6 评论 0原文

我正在编写一个 PHP 函数,该函数将使用一个表格来根据我拥有的日期戳查找应用程序应该转到哪个数据库分片。

分片配置是这样的(伪代码):第一列是我正在查找的事件的日期,第二列是事件所在的分片。

pre-2008 -> shard1
2008-2009 -> shard2
2009_01-2009_06 -> shard3
2009_07 -> shard4
2009_08 -> shard5
2009_09 and up -> shard6

如您所见,我想要的配置非常灵活- 它可以采用任何日期范围,无论大小,并映射到分片。

我正在寻找根据给定日期进行查找的最快方法。

例如,如果我的日期是2009-05-02,那么我所寻找的分片是shard3。如果日期是 2007-08-01,那么它就是 shard1。

实际 PHP 代码的奖励积分,因为应用程序是用 PHP 编写的。

谢谢。

I'm writing a PHP function that would use a table of sorts to look up which DB shard the application should go to, based on the datestamp I have.

The shard configuration is something like this (pseudo-code): the first column is the date of the event I'm looking for and the 2nd is the shard the event resides in.

pre-2008 -> shard1
2008-2009 -> shard2
2009_01-2009_06 -> shard3
2009_07 -> shard4
2009_08 -> shard5
2009_09 and up -> shard6

As you can see, the configuration I want is pretty flexible - it can take any date range, however small or big and map to a shard.

I am looking for the quickest way to do a lookup based on a given date.

For example, if my date is 2009-05-02, the shard I am after is shard3. If the date is 2007-08-01, then it's shard1.

Bonus points for actual PHP code, as the application is in PHP.

Thank you.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

棒棒糖 2024-08-09 07:38:22

我猜您不想希望日期范围中有漏洞,所以我建议您
只需为每个分片指定一个结束日期,并明确命名一个默认分片
它包含所有太新而无法放入其他分片之一的内容。

// configure shards
$SHARDS = array(
        // <end date>   => <shard number>
        '2007-12-31'    => 'shard1', // shard1 - up to end of 2007
        '2008-12-31'    => 'shard2', // shard2 - up to end of 2008
        '2009-06-30'    => 'shard3', // shard3 - up to end of June 09
        '2009-07-31'    => 'shard4', // shard4 - up to end of July 2009
        '2009-08-31'    => 'shard5', // shard4 - up to end of August 2009
        'DEFAULT'       => 'shard6', // everything else in shard 6
        );

这使得获得正确的日期变得容易,并且根据日期查找分片的代码很简单:

function findShardByDate($date) {
    static $default = false;
    static $sorted = false;
    if($sorted === false) {
        // copy of global $SHARDS
        $SHARDS = $GLOBALS['SHARDS'];
        $default = $SHARDS['DEFAULT'];
        unset($SHARDS['DEFAULT']);
        // make sure $SHARDS is sorted
        ksort($SHARDS);
        $sorted = $SHARDS;
        unset($SHARDS);
    }
    // find the first shard which would contain that date
    foreach($sorted as $endDate => $shardName)
        if($endDate >= $date)
            return $shardName;
    // no shard found - use the default shard
    return $default;
}

编辑:使用静态变量,以便排序仅完成一次。

I am guessing that you don't want to have holes in date ranges, so I propose that you
just need to specify an end date for each shard, and explicitly name one Default Shard
which holds everything that is too new to fit into one of the other shards.

// configure shards
$SHARDS = array(
        // <end date>   => <shard number>
        '2007-12-31'    => 'shard1', // shard1 - up to end of 2007
        '2008-12-31'    => 'shard2', // shard2 - up to end of 2008
        '2009-06-30'    => 'shard3', // shard3 - up to end of June 09
        '2009-07-31'    => 'shard4', // shard4 - up to end of July 2009
        '2009-08-31'    => 'shard5', // shard4 - up to end of August 2009
        'DEFAULT'       => 'shard6', // everything else in shard 6
        );

This makes it easy to get the dates right, and the code for finding a shard based on date is simple:

function findShardByDate($date) {
    static $default = false;
    static $sorted = false;
    if($sorted === false) {
        // copy of global $SHARDS
        $SHARDS = $GLOBALS['SHARDS'];
        $default = $SHARDS['DEFAULT'];
        unset($SHARDS['DEFAULT']);
        // make sure $SHARDS is sorted
        ksort($SHARDS);
        $sorted = $SHARDS;
        unset($SHARDS);
    }
    // find the first shard which would contain that date
    foreach($sorted as $endDate => $shardName)
        if($endDate >= $date)
            return $shardName;
    // no shard found - use the default shard
    return $default;
}

Edit: Used static variables so that sorting is only done once.

故事和酒 2024-08-09 07:38:22
<?php

function get_shard($datetime)
{
    $timestamp = strtotime($datetime);

    $shards = array(array('start' => null, 'end' => '2007-12-31'),
                    array('start' => '2008-01-01', 'end' => '2008-12-31'),
                    array('start' => '2009-01-01', 'end' => '2009-06-30'),
                    array('start' => '2009-07-01', 'end' => '2009-07-31'),
                    array('start' => '2009-08-01', 'end' => '2009-08-31'),
                    array('start' => '2009-09-01', 'end' => null),
                    );
    foreach ($shards as $key => $range) {
        $start = strtotime($range['start']);
        $end = strtotime($range['end']);
        if ($timestamp >= $start && $timestamp <= $end) {
            return $key + 1;
        }
        if ($timestamp >= $start && $end === false) {
            return $key + 1;
        }
    }
}


$datetime = '2007-08-01';
echo 'shard' . get_shard($datetime) . "\n";

$datetime = '2009-05-02';
echo 'shard' . get_shard($datetime) . "\n";

$datetime = '2010-01-01';
echo 'shard' . get_shard($datetime) . "\n";

?>

输出:

shard1
shard3
shard6
<?php

function get_shard($datetime)
{
    $timestamp = strtotime($datetime);

    $shards = array(array('start' => null, 'end' => '2007-12-31'),
                    array('start' => '2008-01-01', 'end' => '2008-12-31'),
                    array('start' => '2009-01-01', 'end' => '2009-06-30'),
                    array('start' => '2009-07-01', 'end' => '2009-07-31'),
                    array('start' => '2009-08-01', 'end' => '2009-08-31'),
                    array('start' => '2009-09-01', 'end' => null),
                    );
    foreach ($shards as $key => $range) {
        $start = strtotime($range['start']);
        $end = strtotime($range['end']);
        if ($timestamp >= $start && $timestamp <= $end) {
            return $key + 1;
        }
        if ($timestamp >= $start && $end === false) {
            return $key + 1;
        }
    }
}


$datetime = '2007-08-01';
echo 'shard' . get_shard($datetime) . "\n";

$datetime = '2009-05-02';
echo 'shard' . get_shard($datetime) . "\n";

$datetime = '2010-01-01';
echo 'shard' . get_shard($datetime) . "\n";

?>

Outputs:

shard1
shard3
shard6
烏雲後面有陽光 2024-08-09 07:38:22

由于您的分片可以严格排序,因此似乎将它们存储在二叉树中,然后简单地通过该树运行二分搜索就会给您最快的结果。

Since your shards can be strictly ordered, it seems like storing them in a binary tree and then simply running a binary search through that tree would give you the fastest results.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文