2009-08-17 27 views
1

私は、自分が持っている日付スタンプに基づいて、アプリケーションがどのDBシャードに行くべきかを調べる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上にあるためです。

ありがとうございます。

答えて

2

私はあなたがは、日付範囲の穴を持っている必要はありませんので、私はあなたが だけのため終了日を指定する必要があることを提案することを推測していますそれぞれのシャードと明示的に名前をつけてくださいデフォルトのシャード これは、他のシャードのいずれかに入り込むには新しいものすべてを保持しています。

// 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; 
} 

編集:使用される静的変数をソートするだけで行われるように、一度。

+0

これは高価なので、私はいつも並べ替えや検索をしたくありません。そうでなければ、私はあなたのアプローチが本当に穴がないのが好きです。 –

+0

終了日の代わりに開始日を使用すると、 'DEFAULT'の必要性がなくなります。 –

+0

開始日を使用するには、最初のシャードの前に*何かをキャッチするようにデフォルトが必要です。 –

0

あなたの破片を厳密に注文することができますので、それはあなたの最も速い結果を与えるだろう、バイナリツリーに格納して、単純にそのツリーをバイナリ検索を実行しているように思えます。

2
<?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 
+0

私は考えていますが、あなたの実装にはまだ最適化されていないルックアップがあります。さらに、シャード名を変更する場合や、長いシャード範囲を2つの短いシャド範囲に分割する場合は、関数全体を書き直す必要があります。 –

関連する問題