Существует ли разница в производительности между заявлениями об извлечении 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 BOTH, мне интересно, быстрее ли FETCH ASSOC, когда я собираюсь извлечь много данных; или они одинаковы?
Спасибо
Ответы
Ответ 1
Я хотел узнать ответ на этот вопрос, поэтому написал быстрый тест script.
Я предлагаю вам запустить этот тест на своем собственном сервере, однако это типичный результат в моей настройке, для результатов с одной строкой:
- PDO:: FETCH_ASSOC - 936 мс
- PDO:: FETCH_BOTH - 948 мс
- PDO:: FETCH_NUM - 1,184 мс
- PDO:: FETCH_OBJ - 1,272 мс
- PDO:: FETCH_LAZY - 1,276 мс
Для больших наборов данных эти результаты типичны:
- PDO:: FETCH_LAZY - 5,490 мс
- PDO:: FETCH_NUM - 8,818 мс
- PDO:: FETCH_ASSOC- 10,220 мс
- PDO:: FETCH_BOTH - 11,359 мс
- PDO:: FETCH_OBJ - 14 027 мс
См. комментарии на концентраторе git, выборки всех строк меняют тест.
Ответ 2
Мне интересно, быстрее ли FETCH ASSOC, когда я собираюсь извлечь много данных; или они одинаковы?
Не извлекать много данных, если вам это не нужно. что все.
Как только вам это понадобится - микроскопическая разница между этими методами будет вашей наименьшей проблемой.
Ответ 3
Тест script, отправленный в другом ответе, подсчитывает prepare() и execute() до момента, поэтому я пишу script для тестирования только времени выборки. У меня есть база данных 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.00076103210449219
[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);
Ответ 4
ASSOC, BOTH и OBJ, как правило, одинаковы, за исключением того, что они возвращают другую структуру. Там нет различий в производительности.
LAZY делает какую-то ленивую загрузку. PDO:: FETCH_LAZY создает имена переменных объекта по мере их доступа. Это означает, что вы получаете штраф за исполнение только при доступе к свойствам, а не при вызове fetch(). Это полезно, если вы используете только часть возвращаемых данных.
Ответ 5
Последний ответ глупо ( "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
)
Lazy значение является неполным, так как доступ отсутствует.
но "Оба" на самом деле HAS влияют
вот измененный gist измененный код теста