mysqli або PDO - які плюси і мінуси? [зачинено]


342

В нашому місці ми розділилися між використанням mysqli та PDO для таких матеріалів, як підготовлені заяви та підтримка транзакцій. Деякі проекти використовують один, інші - інший. Мало реальна ймовірність переходу нас до іншої RDBMS.

Я віддаю перевагу PDO з єдиної причини, яка дозволяє вказані параметри для підготовлених операторів, і наскільки я знаю, mysqli цього не робить.

Чи є інші плюси і мінуси вибору одного за іншим як стандарт, коли ми консолідуємо наші проекти, використовуючи лише один підхід?


5
Ця стаття допоможе вибрати, який саме використовувати. Якщо ви вважаєте продуктивність, це може допомогти вам обрати.
ravi404

3
Смішно, скільки людей схвалили та зняли питання, яке не є конструктивним. Вся справа в тому, що повна нитка дуже конструктивна - можливо, модератори повинні враховувати це, коли оцінюють, питання є конструктивним чи ні?
марла

@marlar Я з вами згоден! Це справді найбільша проблема в StackOverflow. Відмінні запитання / дискусії завжди закриваються.
Sliq

Відповіді:


243

Ну, ви можете посперечатися з об'єктно-орієнтованим аспектом, підготовленими висловлюваннями, тим, що це стає стандартом і т. Д. Але я знаю, що більшість часу, переконуючи когось, краще працює з вбивчою рисою. Так ось це:

Дуже приємна річ із PDO - це ви можете отримати дані, автоматично вводячи їх у об’єкт. Якщо ви не хочете використовувати ORM (тому що це просто швидкий сценарій), але вам подобається картографування об'єктів, це дійсно круто:

class Student {

    public $id;
    public $first_name;
    public $last_name

    public function getFullName() {
        return $this->first_name.' '.$this->last_name
    }
}

try 
{
    $dbh = new PDO("mysql:host=$hostname;dbname=school", $username, $password)

    $stmt = $dbh->query("SELECT * FROM students");

    /* MAGIC HAPPENS HERE */

    $stmt->setFetchMode(PDO::FETCH_INTO, new Student);


    foreach($stmt as $student)
    {
        echo $student->getFullName().'<br />';
    } 

    $dbh = null;
}
catch(PDOException $e)
{
    echo $e->getMessage();
}

12
чи є різниця між вищезазначеним і $mysqliResult->fetch_object("student");?
Енді Флемінг

2
@ e-satis ні, я використовую PHP. Публічні поля порушують інкапсуляцію, тому AS A BEST PRACTICEце просто ... lol :) Google не використовує загальнодоступні поля, а лише аксесуари: google-styleguide.googlecode.com/svn/trunk/… .
OZ_

6
@ e-satis: Вибачте, що заскочили, але геттери та сетери необхідні, якщо ви хочете контролювати те, що відбувається при зміні змінних. В іншому випадку ви просто не можете гарантувати внутрішній стан вашого об'єкта (це особливо проблема, якщо у вас є інший об'єкт всередині). Це повністю незалежно від мови. @OZ_: Зробіть полегшення. Особиста критика лише поставить когось іншого на захист.
Джеймс П.

2
@monadic: Погоджено. Інкапсуляція, звичайно, є вагомим аргументом при роботі з основними компонентами, або складними об'єктами тощо, однак як представлення записів, які в іншому випадку були б асоційованими для читання та запису. масиви, це прийнятно. Крім того, це дозволяє простіше перевірити тип, оскільки записи плавають через систему.
Ден Лугг

15
@outis Я сподіваюся, що я тут не серед меншин, але я не вважаю, що відповіді слід судити про їхню безпеку щодо нових розробників. Звучить суворо, але це правда. Мета відповіді на SO - це не просто надати копіювати та вставити код, а й забезпечити розуміння. Завдання відповідача не полягає в тому, щоб у випадку прикладу висвітлювався кожен недолік у захищеному шарі чи шаблоні, тому що, припустимо, це стосується того, що додаток, в який потрапляє код, суттєво відрізняється, ніж будь-яка інша програма, що використовує той самий код.
Mattygabe

57

Переміщення програми з однієї бази даних в іншу не дуже поширене, але рано чи пізно ви можете виявити, що працюєте над іншим проектом, використовуючи інший RDBMS. Якщо ви вдома з PDO, то, принаймні, буде чомусь менше вчитися.

Крім того, я вважаю, що API PDO трохи інтуїтивніше, і він відчуває себе по-справжньому об'єктно орієнтованим. mysqli вважає, що це лише процедурний API, який був об'єктивований, якщо ви знаєте, що я маю на увазі. Коротше кажучи, мені здається, що з PDO простіше працювати, але це, звичайно, суб'єктивно.


25

Я почав використовувати PDO, тому що, на мою думку, підтримка заяв краща. Я використовую рівень доступу до даних ActiveRecord, і реалізувати динамічно створені оператори набагато простіше. Прив’язка параметрів MySQLi повинна виконуватися в одному виклику функції / методу, тому якщо ви не знаєте до часу виконання, скільки параметрів ви хочете прив’язати, ви змушені використовувати call_user_func_array()(я вважаю, це правильна назва функції) для вибору . І забудьте про просте динамічне прив'язування результатів.

Найбільше мені подобається PDO, оскільки це дуже розумний рівень абстракції. Його легко використовувати в повністю абстрагованих системах, де ви не хочете писати SQL, але це також дозволяє легко використовувати більш оптимізований, чистий тип запиту системи або змішувати та узгоджувати ці два.


2
Зв'язування результатів з динамічно генерованими запитами можливо, ми робимо це в наших додатках. Однак це величезний біль.
Пім Джагер

17

PDO - це стандарт, саме те, що очікують використовувати більшість розробників. mysqli по суті був замовником вирішення певної проблеми, але він має всі проблеми інших бібліотек, специфічних для СУБД. PDO - куди піде вся наполеглива праця та розумне мислення.


15

Тут слід пам’ятати ще про щось: наразі (PHP 5.2) бібліотека PDO баггі . Тут повно дивних помилок. Наприклад: перед зберіганням PDOStatementзмінної у змінній слід unset()уникати тонни помилок. Більшість із них були зафіксовані в PHP 5.3, і вони будуть випущені на початку 2009 року в PHP 5.3, що, ймовірно, матиме багато інших помилок. Вам слід зосередитись на використанні PDO для PHP 6.1, якщо ви хочете стабільної версії та використання PDO для PHP 5.3, якщо ви хочете допомогти громаді.


2
Я думаю, що вигоду, яку пропонує PDO, варто розуміти і працювати над помилками. Сам PHP переповнений дуже обтяжуючими помилками, якими ми навіть не можемо ефективно обійтися, і все ж він пропонує безліч переваг, які змушують нас використовувати його замість інших варіантів.
Брайан Варшо

11
Гм, дивно, я ніколи не відчував жодної помилки із PDO. І я цим багато користуюся.
NikiC

У Mysqli також є помилки. Все програмне забезпечення має помилки.
Білл Карвін

10

Ще одна помітна (хороша) відмінність щодо PDO полягає в тому, що його PDO::quote()метод автоматично додає додаються цитати, тоді як mysqli::real_escape_string()(і подібні) не:

PDO :: quote () розміщує лапки навколо рядка введення (якщо потрібно) і уникає спеціальних символів у рядку введення, використовуючи стиль цитування, відповідний базовому драйверу.


8

PDO полегшить масштабність, якщо ваш веб-сайт / веб-додаток дійсно буде таким, як ви можете щодня налаштовувати підключення Master і slave для розподілу навантаження по базі даних, плюс PHP спрямовується на перехід до PDO як стандартного.

Інформація про PDO

Масштабування веб-програми


6

У сенсі швидкості виконання MySQLi виграє, але якщо у вас немає гарної обгортки, яка використовує MySQLi, її функції, що стосуються підготовлених заяв, жахливі.

У мене ще є помилки, але якщо хтось цього хоче, ось він .

Отже, коротше, якщо ви шукаєте збільшення швидкості, то MySQLi; якщо ви хочете зручності використання, тоді PDO.


2
в сенсі швидкості, ви могли б дати орієнтири?
Юлій F

8
Джонатан Робсон зробив гідне порівняння швидкості двох на jonathanrobson.me/2010/06/mysqli-vs-pdo-benchmarks . Підсумок: inserts - майже рівний, selects - mysqli на 2,5% швидший для не підготовлених операторів / ~ 6,7% швидше для підготовлених операторів. З огляду на те, наскільки невеликі штрафи за ефективність, особливості та гнучкість використання в PDOцілому переважають показник ефективності.
Адам

1
@Adam Дякую за посилання на мій блог!
jnrbsn

@ daemonfire300 Це правда, немає необхідності в орієнтирах. PDO обгортає бібліотеку mysqli. Я, мабуть, вдарив би по вентилятору, якби хтось міг довести, що PDO швидше, ніж mysqli. :-D
Дійн

@jnrbsn Чи погоджуєтесь ви з Адамом щодо того, що він сказав?
Базит

5

Особисто я використовую PDO, але я думаю, що це головним чином питання переваги.

PDO має деякі функції, які допомагають отримувати ін'єкцію SQL ( підготовлені заяви ), але якщо ви обережні зі своїм SQL, ви можете домогтися цього і з mysqli.

Перехід до іншої бази даних - це не стільки привід використовувати PDO. Поки ви не використовуєте "спеціальні функції SQL", ви можете переходити з однієї БД в іншу. Однак, як тільки ви використовуєте, наприклад, "SELECT ... LIMIT 1", ви не можете перейти до MS-SQL, де це "SELECT TOP 1 ...". Тож це все одно проблематично.


22
MySQLi підготував заяви.
Вежа

5

Відредагована відповідь.

Маючи певний досвід роботи з обома цими API, я б сказав, що є 2 функції блокуючих рівнів, що робить mysqli непридатним для підготовлених власних операторів.
Про них уже згадувалося у 2 чудових (поки що недооцінених) відповідях:

  1. Прив’язування значень до довільної кількості заповнювачів
  2. Повернення даних як просто масив

(обидва також згадуються у цій відповіді )

Чомусь mysqli провалився з обома.
Сьогодні він отримав деяке вдосконалення для другого ( get_result ), але він працює лише на установках mysqlnd, значить, ви не можете розраховувати на цю функцію у своїх сценаріях.

І все-таки він не має прив'язки до вартості навіть донині.

Отже, є лише один вибір: PDO

Всі інші причини, такі як

  • названі заповнювачі (цей синтаксичний цукор значно завищений)
  • підтримка різних баз даних (ніхто насправді ніколи не використовував її)
  • зайти в об’єкт (просто марний синтаксичний цукор)
  • різниця швидкостей (немає)

не мають важливого значення.

У той же час в обох цих API відсутні деякі реально важливі функції , наприклад

  • ідентифікатор заповнення місця
  • заповнювач місця для складних типів даних, щоб зробити динамічне прив'язування менш обтяжливим
  • коротший код програми.

Отже, для задоволення потреб у реальному житті потрібно створити власну бібліотеку абстракцій на основі одного з цих API, реалізуючи вручну проаналізовані заповнювачі. У цьому випадку я віддаю перевагу mysqli, оскільки вона має менший рівень абстракції.


Нарешті хтось, хто знає і не заперечує фактів життя ...
Іхсан

4

У моєму базовому сценарії кожен метод перевіряється 10000 разів і друкується різниця загального часу для кожного методу. Ви повинні це зробити у власній конфігурації, я впевнений, що результати будуть різними!

Це мої результати:

  • " SELECT NULL" -> PGO()швидше на ~ 0,35 секунди
  • " SHOW TABLE STATUS" -> mysqli()швидше на ~ 2,3 секунди
  • " SELECT * FROM users" -> mysqli()швидше на ~ 33 секунди

Примітка: використовуючи -> fetch_row () для mysqli, імена стовпців не додаються до масиву, я не знайшов способу зробити це в PGO. Але навіть якщо я використовую -> fetch_array (), mysqli трохи повільніше, але все ж швидше, ніж PGO (за винятком SELECT NULL).


17
Що таке PGO? І швидше на 33 секунди ?! Мені дуже важко повірити ...
Алікс Аксель,

3

Одне з PDO полягає в тому, що MySQLi не дуже мені подобається - це здатність PDO повертати результат у вигляді об'єкта заданого типу класу (наприклад $pdo->fetchObject('MyClass')). MySQLi fetch_object()поверне лише stdClassоб'єкт.


19
Власне, ви можете вказати клас вручну: "object mysqli_result :: fetch_object ([рядок $ class_name [, масив $ params]])". stdClass використовується, лише якщо ви нічого не вказуєте.
Андріоїд

-4

Майте на увазі одну річ.

Mysqli не підтримує функцію fetch_assoc (), яка б повертала стовпці з ключами, що представляють назви стовпців. Звичайно, можна написати свою власну функцію, щоб це зробити, це навіть не дуже довго, але мені було дуже важко писати це (для невіруючих: якщо вам здається легко, спробуйте це самостійно і не робіть цього " т обману :))


4
Ви спробували посібник? php.net/manual/en/mysqli-result.fetch-assoc.php
до

2
Впроваджувався давно, але так, я перевірив посібник. Чи працює це з підготовленими заявами? Сумніваюсь ...
Майк

2
Насправді вона має цікаво часткову підтримку. Ви можете отримати масиви в звичайних запитах, але не в параметризованих запитах: -!
Альваро Гонсалес

1
Чому б не видалити відповідь, яка, очевидно, неправильна?
Маджід Фуладпур

2
@MajidFouladpour - відповідь, очевидно, неправильна . Просто не вистачає якогось контексту. Mysqli не повністю підтримує пошук асоціативного масиву.
Альваро Гонсалес
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.