2010-07-25 12 views
21

как вСуществует ли разница в производительности между заявлениями на выборку PDO?

/* Exercise PDOStatement::fetch styles */ 
print("PDO::FETCH_ASSOC: "); 
print("Return next row as an array indexed by column name\n"); 
$result = $sth->fetch(PDO::FETCH_ASSOC); 
print_r($result); 
print("\n"); 

print("PDO::FETCH_BOTH: "); 
print("Return next row as an array indexed by both column name and number\n"); 
$result = $sth->fetch(PDO::FETCH_BOTH); 
print_r($result); 
print("\n"); 

print("PDO::FETCH_LAZY: "); 
print("Return next row as an anonymous object with column names as properties\n"); 
$result = $sth->fetch(PDO::FETCH_LAZY); 
print_r($result); 
print("\n"); 

print("PDO::FETCH_OBJ: "); 
print("Return next row as an anonymous object with column names as properties\n"); 
$result = $sth->fetch(PDO::FETCH_OBJ); 
print $result->NAME; 
print("\n"); 

Ну по умолчанию является FETCH ОБА, мне интересно, если FETCH ASSOC быстрее, когда я собираюсь принести много данных; или они одинаковы?

Благодаря

ответ

2

ASSOC, ОБА и OBJ, как правило, то же самое, за исключением того, что они возвращают другую структуру. Там нет различий в производительности.

LAZY делает какую-то ленивую загрузку. PDO :: FETCH_LAZY создает имена переменных объекта по мере их доступа. Это означает, что вы получаете штраф за исполнение только при доступе к свойствам, а не при вызове fetch(). Это полезно, если вы используете только часть возвращаемых данных.

+2

Есть ли ситуация, когда отложенная загрузка снижает производительность? –

+0

ну, я действительно не пробовал, но я уверен, что разница незначительна. но я действительно не сейчас. –

+1

«Это полезно, если вы используете только часть возвращаемых данных». Почему вы запрашиваете данные, которые не собираетесь использовать? Или это вопрос лучше, слишком много, вместо того, чтобы снова запрашивать? – PeeHaa

32

Я хотел знать ответ на этот вопрос, поэтому я написал быстрый benchmark script.

Я предлагаю вам запустить этот тест на свой собственный сервер, однако, это типичный результат на моей установке, для отдельных результатов строк:

  1. PDO :: FETCH_ASSOC - 936 мс
  2. PDO :: FETCH_BOTH - 948 мс
  3. PDO :: FETCH_NUM - 1,184 мс
  4. PDO :: FETCH_OBJ - 1,272 мс
  5. PDO :: FETCH_LAZY - 1,276 мс

Для больших наборов данных, эти результаты являются типичными:

  1. PDO :: FETCH_LAZY - 5,490 мс
  2. PDO :: FETCH_NUM - 8818 мс
  3. PDO :: FETCH_ASSOC- 10220 мс
  4. ПДО :: FETCH_BOTH - 11,359 мс
  5. PDO :: FETCH_OBJ - 14,027 мс

Смотрите комментарии на мерзавца ступице, кокетливыми все ро ws меняет тест.

+1

Буду признателен за обратную связь на нижнем уровне. Это единственный количественный ответ на этот вопрос. – GateKiller

+0

Мне очень больно иметь нисходящий пояс без объяснения причин. Ну, с моим upvote, вы вернулись на круги своя. Я имею в виду квадратный нуль. Спасибо за тест и скрипт. Возможно, одно повышение. Я думаю, что использование данных должно быть частью теста, поскольку доступ к массиву или объекту может также привести к разнице в сроках. Кроме того, может быть даже разница в запросе данных из большого массива или большого объекта. –

+0

Примечание. Лень будет стоить дороже, если вы вытащите все параметры из результата. Я думаю, это полезно, когда вы получаете огромный отклик и нуждаетесь только в доле. – michaelbn

3

Мне интересно, если FETCH ASSOC быстрее, когда я собираюсь получить много данных; или они одинаковы?

Не принести много данных, когда это не нужно. это все.

Как только это вам понадобится - микроскопическая разница между этими методами будет вашей наименьшей проблемой.

+1

Это не ответ на вопрос – Finesse

+0

Жаль, что подавляющее большинство пользователей PHP не понимают, что это единственный ответ. Но для языка, на котором каждый ученик считает себя экспертом, это довольно нормально. –

+0

@ ваш-общий-я согласен с вами ответить, но это ответ на другой вопрос – Finesse

-2

Последний ответ глупо («do not fetch ....»): что делать, если вам нужно преобразовать данные для большой таблицы или таблиц интерфейса dbs?

Я изменил код бенчмаркинга выше, потому что он не тестировал корректно IMHO (одного одиночного извлечения за цикл недостаточно ;-)), я заменил его на 10000 записей х 100 циклов на тип выборки.

Я добавил Fetch_class, который был вопросом, который у меня был для меня. Я добавил настоящий класс, чтобы быть уверенным, что последний тест был правильным.

результаты (упорядоченные):

Array 
(
    [Lazy] => 88.43896484375 
    [Num] => 281.11694335938 
    [Assoc] => 310.59375 
    [Class] => 384.8310546875 
    [Obj] => 395.36401367188 
    [Both] => 411.62109375 
) 

Ленивый значение является неполным, так как нет доступа. но «Оба» на самом деле HAS влияние

здесь модифицированный сутью modified Benchmark code

+0

В другом ответе также говорится: «Как только вам это понадобится [большие данные] - микроскопическая разница между этими методами будет вашей наименьшей проблемой». Некоторые пользователи PHP не имеют здравого смысла и не будут использовать ** метод, соответствующий их потребностям **, но тот, который является мнимым «быстрее». –

+1

Вправо. Т.е. я бы всегда рекомендовал Assoc, потому что вам не нужен доступ Num, даже если он быстрее. И я обнаружил, что Assoc всегда лучше Class, потому что вы можете «пропустить» данные, если prop не определен. – Nadir

3

Эталонный сценарий писал в другой ответ рассчитывает подготовить() и выполнить() в то время, так что я пишу скрипт для тестирования только времени выборки. У меня есть база данных MySQL, содержащая около 100000 строк реальных данных. LongRow содержит столбец TEXT (около 4 кбайт данных в строке). ShortRow (30 байт в строке). FETCH_INTO использует предопределенный класс со всеми свойствами столбца. PHP версия 5.4. MySQL 5.5.35. Здесь одна вещь отсутствует: среднее количество пробегов.

 
Array 
(
    [Items: 10] => Array 
     (
      [ShortRow] => Array 
       (
        [FETCH_INTO] => 0.0001068115234375 
        [FETCH_OBJECT] => 0.00013899803161621 
        [FETCH_COLUMN (STR8)] => 6.0081481933594E-5 
        [FETCH_COLUMN (INT)] => 5.8174133300781E-5 
        [FETCH_NUM] => 9.2029571533203E-5 
        [FETCH_ASSOC] => 9.8943710327148E-5 
        [FETCH_BOTH] => 0.00011897087097168 
        [FETCH_LAZY] => 6.3180923461914E-5 
       ) 

      [LongRow] => Array 
       (
        [FETCH_INTO] => 0.00012779235839844 
        [FETCH_OBJECT] => 0.00016498565673828 
        [FETCH_COLUMN (TEXT)] => 4.9829483032227E-5 
        [FETCH_COLUMN (INT)] => 4.3153762817383E-5 
        [FETCH_NUM] => 0.00010180473327637 
        [FETCH_ASSOC] => 0.00010895729064941 
        [FETCH_BOTH] => 0.00013399124145508 
        [FETCH_LAZY] => 4.3869018554688E-5 
       ) 

     ) 

    [Items: 100] => Array 
     (
      [ShortRow] => Array 
       (
        [FETCH_INTO] => 0.00081610679626465 
        [FETCH_OBJECT] => 0.0011789798736572 
        [FETCH_COLUMN (STR8)] => 0.00040292739868164 
        [FETCH_COLUMN (INT)] => 0.00041294097900391 
        [FETCH_NUM] => 0.00067806243896484 
        [FETCH_ASSOC] => 0.449219 
        [FETCH_BOTH] => 0.00092482566833496 
        [FETCH_LAZY] => 0.00043201446533203 
       ) 

      [LongRow] => Array 
       (
        [FETCH_INTO] => 0.0010471343994141 
        [FETCH_OBJECT] => 0.0013670921325684 
        [FETCH_COLUMN (TEXT)] => 0.00037693977355957 
        [FETCH_COLUMN (INT)] => 0.00030612945556641 
        [FETCH_NUM] => 0.00079894065856934 
        [FETCH_ASSOC] => 0.00094914436340332 
        [FETCH_BOTH] => 0.0011270046234131 
        [FETCH_LAZY] => 0.00031089782714844 
       ) 

     ) 

    [Items: 1000] => Array 
     (
      [ShortRow] => Array 
       (
        [FETCH_INTO] => 0.0082287788391113 
        [FETCH_OBJECT] => 0.0099248886108398 
        [FETCH_COLUMN (STR8)] => 0.0037147998809814 
        [FETCH_COLUMN (INT)] => 0.0038070678710938 
        [FETCH_NUM] => 0.006443977355957 
        [FETCH_ASSOC] => 0.0070838928222656 
        [FETCH_BOTH] => 0.008652925491333 
        [FETCH_LAZY] => 0.0039060115814209 
       ) 

      [LongRow] => Array 
       (
        [FETCH_INTO] => 0.0092909336090088 
        [FETCH_OBJECT] => 0.011745929718018 
        [FETCH_COLUMN (TEXT)] => 0.0031650066375732 
        [FETCH_COLUMN (INT)] => 0.0025970935821533 
        [FETCH_NUM] => 0.0068809986114502 
        [FETCH_ASSOC] => 0.0087978839874268 
        [FETCH_BOTH] => 0.010183811187744 
        [FETCH_LAZY] => 0.0026650428771973 
       ) 

     ) 

    [Items: 10000] => Array 
     (
      [ShortRow] => Array 
       (
        [FETCH_INTO] => 0.067224025726318 
        [FETCH_OBJECT] => 0.086459159851074 
        [FETCH_COLUMN (STR8)] => 0.03191089630127 
        [FETCH_COLUMN (INT)] => 0.031462907791138 
        [FETCH_NUM] => 0.047988891601562 
        [FETCH_ASSOC] => 0.05333399772644 
        [FETCH_BOTH] => 0.065713882446289 
        [FETCH_LAZY] => 0.028834819793701 
       ) 

      [LongRow] => Array 
       (
        [FETCH_INTO] => 0.12389183044434 
        [FETCH_OBJECT] => 0.15812706947327 
        [FETCH_COLUMN (TEXT)] => 0.03816294670105 
        [FETCH_COLUMN (INT)] => 0.035914897918701 
        [FETCH_NUM] => 0.1117901802063 
        [FETCH_ASSOC] => 0.10923099517822 
        [FETCH_BOTH] => 0.12394094467163 
        [FETCH_LAZY] => 0.030914068222046 
       ) 

     ) 

) 

Вот код тоже:



    //Code is missing connect to DB 
    header('Content-Type: text/plain'); 
    class testModel1 { 
     public $id; 
     public $invoice; 
     public $transaction; 
     public $creditedInvoice; 
     public $amount; 
     public $payment_type; 
     public $currency; 
     public $created; 
     public $timestamp; 
    } 

    class testModel2 { 
     public $id; 
     public $cid; 
     public $c_amount; 
     public $object; 
     public $person; 
     public $date; 
     public $type; 
     public $invoice_type; 
     public $version; 
     public $templateInvoice; 
     public $account; 
     public $variable_symbol; 
     public $number; 
     public $accounting_year; 
     public $amount; 
     public $currency; 
     public $comment; 
     public $data; //is a text column (avg size about 4kB) 
     public $created; 
     public $modified; 
     public $timestamp; 
    } 
    $items = array(10,100,1000,10000); 
    foreach($items as $item) { 
     $ivStmt = $pdo->prepare("SELECT * FROM `invoices_paying` LIMIT $item"); 
     $ivStmt->execute(array('items'=>$item)); 
     $out = array(); 
     $testModel1 = new testModel1(); 
     $ivStmt->setFetchMode(PDO::FETCH_INTO, $testModel1); 
     $start = microtime(true); 
     while($id = $ivStmt->fetch()) { 
     } 
     $end = microtime(true); 
     $out['FETCH_INTO'] = $end-$start; 

     $ivStmt->execute(array('items'=>$item)); 
     $start = microtime(true); 
     while($id = $ivStmt->fetchObject()) { 
     } 
     $end = microtime(true); 
     $out['FETCH_OBJECT'] = $end-$start; 

     $ivStmt->execute(array('items'=>$item)); 
     $start = microtime(true); 
     while($id = $ivStmt->fetchColumn(5)) { 
     } 
     $end = microtime(true); 
     $out['FETCH_COLUMN (STR8)'] = $end-$start; 

     $ivStmt->execute(array('items'=>$item)); 
     $start = microtime(true); 
     while($id = $ivStmt->fetchColumn(0)) { 
     } 
     $end = microtime(true); 
     $out['FETCH_COLUMN (INT)'] = $end-$start; 

     $ivStmt->execute(array('items'=>$item)); 
     $start = microtime(true); 
     while($id = $ivStmt->fetch(PDO::FETCH_NUM)) { 
     } 
     $end = microtime(true); 
     $out['FETCH_NUM'] = $end-$start; 

     $ivStmt->execute(array('items'=>$item)); 
     $start = microtime(true); 
     while($id = $ivStmt->fetch(PDO::FETCH_ASSOC)) { 
     } 
     $end = microtime(true); 
     $out['FETCH_ASSOC'] = $end-$start; 

     $ivStmt->execute(array('items'=>$item)); 
     $start = microtime(true); 
     while($id = $ivStmt->fetch(PDO::FETCH_BOTH)) { 
     } 
     $end = microtime(true); 
     $out['FETCH_BOTH'] = $end-$start; 

     $ivStmt->execute(array('items'=>$item)); 
     $start = microtime(true); 
     while($id = $ivStmt->fetch(PDO::FETCH_LAZY)) { 
     } 
     $end = microtime(true); 
     $out['FETCH_LAZY'] = $end-$start; 

     $table['Items: '.$item]['ShortRow'] = $out; 
    } 
    foreach($items as $item) { 
     $ivStmt = $pdo->prepare("SELECT * FROM `invoices` LIMIT $item"); 
     $ivStmt->execute(array('items'=>$item)); 
     $out = array(); 
     $testModel2 = new testModel2(); 
     $ivStmt->setFetchMode(PDO::FETCH_INTO, $testModel2); 
     $start = microtime(true); 
     while($id = $ivStmt->fetch()) { 
     } 
     $end = microtime(true); 
     $out['FETCH_INTO'] = $end-$start; 

     $ivStmt->execute(array('items'=>$item)); 
     $start = microtime(true); 
     while($id = $ivStmt->fetchObject()) { 
     } 
     $end = microtime(true); 
     $out['FETCH_OBJECT'] = $end-$start; 

     $ivStmt->execute(array('items'=>$item)); 
     $start = microtime(true); 
     while($id = $ivStmt->fetchColumn(17)) { 
     } 
     $end = microtime(true); 
     $out['FETCH_COLUMN (TEXT)'] = $end-$start; 

     $ivStmt->execute(array('items'=>$item)); 
     $start = microtime(true); 
     while($id = $ivStmt->fetchColumn(0)) { 
     } 
     $end = microtime(true); 
     $out['FETCH_COLUMN (INT)'] = $end-$start; 

     $ivStmt->execute(array('items'=>$item)); 
     $start = microtime(true); 
     while($id = $ivStmt->fetch(PDO::FETCH_NUM)) { 
     } 
     $end = microtime(true); 
     $out['FETCH_NUM'] = $end-$start; 

     $ivStmt->execute(array('items'=>$item)); 
     $start = microtime(true); 
     while($id = $ivStmt->fetch(PDO::FETCH_ASSOC)) { 
     } 
     $end = microtime(true); 
     $out['FETCH_ASSOC'] = $end-$start; 

     $ivStmt->execute(array('items'=>$item)); 
     $start = microtime(true); 
     while($id = $ivStmt->fetch(PDO::FETCH_BOTH)) { 
     } 
     $end = microtime(true); 
     $out['FETCH_BOTH'] = $end-$start; 

     $ivStmt->execute(array('items'=>$item)); 
     $start = microtime(true); 
     while($id = $ivStmt->fetch(PDO::FETCH_LAZY)) { 
     } 
     $end = microtime(true); 
     $out['FETCH_LAZY'] = $end-$start; 

     $table['Items: '.$item]['LongRow'] = $out; 
    } 
    print_r($table);