課題 #997

CSVの読み込み処理を改善する

Added by ryuring   almost 2 years ago. Updated over 1 year ago.

Status:担当 Start date:06/09/2010
Priority:高め Due date:
Assignee:- % Done:

0%

Category:その他
Target version:-

Description

ページ機能において、サーバーキャッシュがない場合に、表示速度が極端に遅くなる。

現在、データベースとして「CSV」を利用する場合、SQLでよくある、「並び替え処理を行った上で、◯番目から◯件を取得する」という要件を満たす為に、一旦全てのデータをメモリに置いてから処理を行っている。
その場合、大量のデータを扱う場合、処理速度が極端に落ちてしまう。

◯番目からという指定がなく、先頭から指定件数を取得するという事であれば、指定件数分の配列を用意してやりロケット鉛筆方式で、メモリ消費量を最小限に抑えて実装可能だが、◯番目からという指定がある場合は??

要件

  • ランダムにならんだデータを昇順、もしくは降順に並び替えた上で、◯番目から◯件取得できる。(◯には任意の数字が入る)
  • データにはCSVの1レコードが入る為、大量件数の場合を考えて、全データをメモリ上にのせずに処理をさせたい。

先頭から指定件数取得するサンプル(ここではただの配列ですが、実際はファイル読み込みとなります)

$file = array(1,7,10,8,0,4,6,8,5,2,3,4,3,0,0,11,1000);
$max = 9;
$conditions = '$line >= 9';
$order = 'DESC';
var_dump(readData($file,$max,$conditions,$order));

function readData($file, $max, $conditions, $order = 'ASC'){
    $stack=array();
    $i=0;
    while($i<$max){
        $stack[] = null;
        $i++;
    }
    foreach($file as $line){
        if($order == 'ASC' && (!is_null($stack[$max-1]) && $stack[$max-1] <= $line)) continue;
        if($order == 'DESC' && (!is_null($stack[$max-1]) && $stack[$max-1] >= $line)) continue;
        if(!eval('if('.$conditions.') return true;')) continue;

        $idx = getIndex($stack, $line, 0, $max-1, $order);
        for($i=$max-1; $i>=$idx+1; --$i) {
            $stack[$i]=$stack[$i-1];
        }
        $stack[$idx] = $line;
    }
    foreach($stack as $key => $value){
        if(is_null($value)){
            unset($stack[$key]);
        }
    }
    return $stack;
}

function getIndex($stack, $line, $start, $end, $order='ASC'){
    if($end < 0){
        return 0;
    }
    $mid = (int)(($start + $end) / 2);
    $target = $stack[$mid];
    if($target === $line){
        return $mid;
    }elseif($order=='ASC' && (is_null($target) || $target > $line)){
        if(!is_null($stack[$mid-1]) && $stack[$mid-1] < $line){
            return $mid;
        }else{
            return getIndex($stack, $line, $start, $mid-1, $order);
        }
    }elseif($order=='DESC' && (is_null($target) || $target < $line)){
        if(!is_null($stack[$mid-1]) && $stack[$mid-1] > $line){
            return $mid;
        }else{
            return getIndex($stack, $line, $start, $mid-1, $order);
        }
    } else {
        return getIndex($stack, $line, $mid+1, $end, $order);
    }
}

History

Updated by ryuring   almost 2 years ago

  • Assignee set to ryuring  
  • Target version set to BaserCMS 1.5.8

Updated by ryuring   almost 2 years ago

  • Target version deleted (BaserCMS 1.5.8)

Updated by ryuring   almost 2 years ago

  • Priority changed from 急いで to 高め

Updated by ryuring   over 1 year ago

  • Assignee deleted (ryuring  )

Also available in: Atom PDF