mysqli lub PDO - jakie są zalety i wady? [Zamknięte]

342

W naszym przypadku jesteśmy podzieleni między używanie mysqli i PDO do takich rzeczy jak przygotowane wyciągi i obsługa transakcji. Niektóre projekty używają jednego, inne drugiego. Niewielkie realne prawdopodobieństwo, że kiedykolwiek przeprowadzimy się do innego RDBMS.

Wolę PDO z tego samego powodu, że pozwala on na nazwane parametry dla przygotowanych instrukcji i o ile wiem, mysqli nie.

Czy są jakieś inne zalety i wady, aby wybierać jeden nad drugim jako standard, gdy konsolidujemy nasze projekty, aby zastosować tylko jedno podejście?

Polsonby
źródło
5
Ten artykuł pomoże wybrać, którego użyć. Jeśli weźmiesz pod uwagę wydajność, może ci to pomóc.
ravi404
3
To zabawne, jak wiele osób wyraziło opinię i zagłosowało na pytanie, które nie jest „konstruktywne”. Chodzi o to, że pełny wątek jest bardzo konstruktywny - może moderatorzy powinni wziąć to pod uwagę, oceniając, czy pytanie jest konstruktywne, czy nie?
marlar
@marlar Zgadzam się z tobą! To jest rzeczywiście największy problem na StackOverflow. Doskonałe pytania / dyskusje są zawsze zamknięte.
Sliq,

Odpowiedzi:

243

Cóż, można spierać się z aspektem obiektowym, przygotowanymi stwierdzeniami, faktem, że staje się standardem itp. Ale wiem, że przez większość czasu przekonywanie kogoś działa lepiej z funkcją zabójcy. Oto on:

Naprawdę fajną rzeczą w PDO jest to, że możesz pobrać dane, wstrzykując je automatycznie do obiektu. Jeśli nie chcesz używać ORM (ponieważ jest to tylko szybki skrypt), ale lubisz mapowanie obiektów, to NAPRAWDĘ fajne:

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();
}
e-satis
źródło
12
czy jest jakaś różnica między powyższym a $mysqliResult->fetch_object("student");?
Andy Fleming,
2
@ e-satis nie, używam PHP. Pola publiczne naruszają enkapsulację, więc AS A BEST PRACTICEto po prostu ... lol :) Google nie korzysta z pól publicznych, tylko akcesoria: google-styleguide.googlecode.com/svn/trunk/… .
OZ_
6
@ e-satis: Przepraszam za wskakiwanie, ale operatory pobierające i ustawiające są konieczne, jeśli chcesz kontrolować, co się stanie, gdy zmienne zostaną zmienione. W przeciwnym razie po prostu nie możesz zagwarantować wewnętrznego stanu swojego obiektu (jest to szczególnie problem, jeśli masz w środku inny obiekt). Jest to całkowicie niezależne od języka. @OZ_: Rozluźnij się. Osobista krytyka wystawi tylko kogoś na obronę.
James P.
2
@monadic: Uzgodniony. Hermetyzacja jest oczywiście ważnym argumentem w kontaktach z podstawowymi komponentami lub złożonymi obiektami itp., Jednak jako reprezentacja rekordów, które w innym przypadku byłyby skojarzone z odczytem i zapisem. tablice, jest to do przyjęcia. Ponadto umożliwia łatwiejsze sprawdzanie typu, ponieważ rekordy płyną w systemie.
Dan Lugg
15
@outis Mam nadzieję, że nie jestem tutaj w mniejszości, ale nie sądzę, że odpowiedzi należy oceniać na podstawie ich bezpieczeństwa w stosunku do nowych programistów. Brzmi ostro, ale to prawda. Celem odpowiedzi w SO jest nie tylko dostarczenie kodu kopiuj i wklej, ale także zrozumienie. Zadaniem osoby odpowiadającej nie jest upewnienie się, że każda dziura w zabezpieczeniach lub luka w zabezpieczeniach są objęte przykładem, ponieważ spójrzmy prawdzie w oczy, aplikacja, do której kopiowany jest kod, jest z natury inna niż każda inna aplikacja używająca tego samego kodu.
Mattygabe,
57

Przenoszenie aplikacji z jednej bazy danych do drugiej nie jest zbyt częste, ale prędzej czy później może się okazać, że pracujesz nad innym projektem przy użyciu innego RDBMS. Jeśli jesteś w domu z PDO, w tym momencie będzie co najmniej jedna rzecz do nauczenia się.

Poza tym uważam, że API PDO jest nieco bardziej intuicyjne i wydaje się bardziej zorientowane obiektowo. mysqli uważa, że ​​jest to po prostu proceduralny interfejs API, który został zobiektywizowany, jeśli wiesz, co mam na myśli. Krótko mówiąc, uważam, że PDO jest łatwiejsze do pracy, ale jest to oczywiście subiektywne.

Theo
źródło
25

Zacząłem używać PDO, ponieważ moim zdaniem obsługa instrukcji jest lepsza. Korzystam z warstwy dostępu do danych w formacie ActiveRecord i znacznie łatwiej jest implementować dynamicznie generowane instrukcje. Powiązanie parametrów MySQLi musi być wykonane w pojedynczym wywołaniu funkcji / metody, więc jeśli do czasu uruchomienia nie wiesz, ile parametrów chcesz powiązać, musisz użyć call_user_func_array()(uważam, że to właściwa nazwa funkcji) do selekcji . I zapomnij o prostym dynamicznym wiązaniu wyników.

Przede wszystkim lubię PDO, ponieważ jest to bardzo rozsądny poziom abstrakcji. Łatwo go używać w całkowicie abstrakcyjnych systemach, w których nie chcesz pisać SQL, ale ułatwia także korzystanie z bardziej zoptymalizowanego, czystego typu zapytań systemu lub mieszanie i łączenie tych dwóch.

Brian Warshaw
źródło
2
Wiązanie wyników z dynamicznie generowanymi zapytaniami jest możliwe, robimy to w naszych aplikacjach. Jest to jednak ogromny ból.
Pim Jager
17

PDO to standard, którego większość programistów będzie oczekiwać. mysqli było zasadniczo indywidualnym rozwiązaniem konkretnego problemu, ale ma wszystkie problemy z innymi bibliotekami specyficznymi dla DBMS. PDO to miejsce, gdzie idzie cała ciężka praca i sprytne myślenie.

Dave Gregory
źródło
15

Oto jeszcze jedna rzecz, o której należy pamiętać: na razie (PHP 5.2) biblioteka PDO jest wadliwa . Jest pełen dziwnych błędów. Na przykład: przed zapisaniem PDOStatementzmiennej w zmiennej należy unset()unikać mnóstwa błędów. Większość z nich została naprawiona w PHP 5.3 i zostaną wydane na początku 2009 roku w PHP 5.3, który prawdopodobnie będzie zawierał wiele innych błędów. Powinieneś skupić się na używaniu PDO dla PHP 6.1, jeśli chcesz stabilnej wersji i używania PDO dla PHP 5.3, jeśli chcesz pomóc społeczności.

Tomek
źródło
2
Myślę, że korzyści, które oferuje PDO, są warte zrozumienia i obejścia błędów. Sam PHP jest pełen bardzo obciążających błędów, z których niektóre nie są w stanie skutecznie obejść, a jednak oferuje wiele korzyści, które powodują, że używamy go zamiast innych opcji.
Brian Warshaw,
11
Uhm, dziwne, nigdy nie spotkałem się z żadnym błędem w PDO. I często go używam.
NikiC
Mysqli ma również błędy. Całe oprogramowanie zawiera błędy.
Bill Karwin,
10

Kolejną istotną (dobrą) różnicą dotyczącą PDO jest to, że PDO::quote()metoda ta automatycznie dodaje otaczające cytaty, podczas gdy mysqli::real_escape_string()(i podobne) nie:

PDO :: quote () umieszcza cudzysłowy wokół ciągu wejściowego (jeśli jest wymagany) i ucieka ze znaków specjalnych w ciągu wejściowym, używając stylu cytowania odpowiedniego dla danego sterownika.

Alix Axel
źródło
8

PDO znacznie ułatwi skalowanie, jeśli twoja witryna / aplikacja internetowa naprawdę działa, ponieważ możesz codziennie konfigurować połączenia Master i Slave, aby rozłożyć obciążenie w bazie danych, a PHP zmierza w kierunku przejścia na PDO jako standard.

Informacje o PDO

Skalowanie aplikacji internetowej

Dfranc3373
źródło
6

W sensie szybkości wykonania MySQLi wygrywa, ale jeśli nie masz dobrego opakowania używającego MySQLi, jego funkcje dotyczące przygotowanych instrukcji są okropne.

W moim nadal są błędy, ale jeśli ktoś tego chce, oto jest .

Krótko mówiąc, jeśli szukasz przyspieszenia, to MySQLi; jeśli chcesz łatwości użytkowania, to PDO.

Ry-
źródło
2
w sensie prędkości, czy mógłbyś podać wzorce?
Julius F
8
Jonathen Robson dokonał przyzwoitego porównania prędkości dwóch na jonathanrobson.me/2010/06/mysqli-vs-pdo-benchmarks . Podsumowanie: inserts - prawie równy, selects - mysqli jest ~ 2,5% szybszy w przypadku nieprzygotowanych instrukcji / ~ 6,7% szybszy w przypadku przygotowanych instrukcji. Biorąc pod uwagę, jak niewielkie są kary za wydajność, cechy i elastyczność użytkowania PDOprzeważają nad wydajnością.
Adam
1
@Adam Dzięki za link do mojego bloga!
jnrbsn
@ daemonfire300 To prawda, nie ma potrzeby przeprowadzania testów porównawczych. PDO otacza bibliotekę mysqli. Prawdopodobnie uderzyłbym w wentylator, gdyby ktoś mógł udowodnić, że PDO jest szybszy niż mysqli. :-D
Dyin
@ jnrbsn zgadzasz się z Adamem co powiedział?
Basit
5

Osobiście używam PDO, ale myślę, że to głównie kwestia preferencji.

PDO ma pewne funkcje, które pomagają w iniekcji SQL ( przygotowane instrukcje ), ale jeśli jesteś ostrożny z SQL, możesz to również osiągnąć za pomocą mysqli.

Przeniesienie do innej bazy danych to nie tyle powód, by używać PDO. Dopóki nie używasz „specjalnych funkcji SQL”, możesz przełączać się z jednego DB na inny. Jednak jak tylko użyjesz na przykład „WYBIERZ ... LIMIT 1”, nie możesz przejść do MS-SQL, gdzie jest to „WYBIERZ TOP 1 ...”. To i tak jest problematyczne.

BlaM
źródło
22
MySQLi przygotował wyciągi.
Tower
5

Edytowana odpowiedź.

Po pewnym doświadczeniu z obydwoma interfejsami API powiedziałbym, że istnieją 2 funkcje poziomu blokowania, które sprawiają, że mysqli nie nadaje się do użycia z natywnie przygotowanymi instrukcjami.
Zostały one już wspomniane w 2 doskonałych (ale niedocenianych) odpowiedziach:

  1. Powiązanie wartości z dowolną liczbą symboli zastępczych
  2. Zwracanie danych jako zwykła tablica

(oba wymienione również w tej odpowiedzi )

Z jakiegoś powodu mysqli zawiodło w obu przypadkach.
Obecnie poprawiono go w stosunku do drugiego ( get_result ), ale działa tylko na instalacjach mysqlnd, co oznacza, że ​​nie możesz polegać na tej funkcji w swoich skryptach.

Jednak do dnia dzisiejszego nie ma wiążącej wartości.

Jest więc tylko jeden wybór: ChNP

Wszystkie inne powody, takie jak

  • nazwane symbole zastępcze (ta cukier składniowy jest zdecydowanie przereklamowany)
  • obsługa różnych baz danych (nikt tak naprawdę nigdy z niego nie korzystał)
  • pobierz do obiektu (po prostu bezużyteczny cukier składniowy)
  • różnica prędkości (nie ma żadnej)

nie mają istotnego znaczenia.

Jednocześnie w obu tych interfejsach API brakuje niektórych naprawdę ważnych funkcji , takich jak

  • identyfikator symbolu zastępczego
  • symbol zastępczy dla złożonych typów danych, aby wiązanie dynamiczne było mniej uciążliwe
  • krótszy kod aplikacji.

Tak więc, aby zaspokoić rzeczywiste potrzeby, trzeba stworzyć własną bibliotekę abstrakcji, opartą na jednym z tych interfejsów API, implementującą ręcznie parsowane symbole zastępcze. W tym przypadku wolę mysqli, ponieważ ma mniejszy poziom abstrakcji.

Twój zdrowy rozsądek
źródło
Wreszcie ktoś, kto zna i nie zaprzecza faktom życia ...
Ihsan
4

W moim skrypcie testowym każda metoda jest testowana 10000 razy i drukowana jest różnica całkowitego czasu dla każdej metody. Powinieneś to zrobić we własnej konfiguracji, jestem pewien, że wyniki będą się różnić!

Oto moje wyniki:

  • SELECT NULL" -> PGO()szybciej o ~ 0,35 sekundy
  • SHOW TABLE STATUS" -> mysqli()szybciej o ~ 2,3 sekundy
  • SELECT * FROM users" -> mysqli()szybciej o ~ 33 sekund

Uwaga: używając -> fetch_row () dla mysqli, nazwy kolumn nie są dodawane do tablicy, nie znalazłem sposobu na zrobienie tego w PGO. Ale nawet jeśli użyję -> fetch_array (), mysqli jest nieco wolniejszy, ale wciąż szybszy niż PGO (z wyjątkiem SELECT NULL).

Dobb
źródło
17
Co to jest PGO? I szybciej o 33 sekundy ? Bardzo trudno mi w to uwierzyć ...
Alix Axel
3

PDO ma jedną cechę, której MySQLi tak naprawdę nie podoba mi się, że PDO może zwrócić wynik jako obiekt określonego typu klasy (np $pdo->fetchObject('MyClass').). MySQLi fetch_object()zwróci tylko stdClassobiekt.

Nieoznakowane Mięso
źródło
19
W rzeczywistości można ręcznie określić klasę: „object mysqli_result :: fetch_object ([string $ nazwa_klasy [, tablica $ params]])”. stdClass jest używane tylko wtedy, gdy niczego nie określisz.
Andrioid
-4

Należy pamiętać o jednej rzeczy.

Mysqli nie obsługuje funkcji fetch_assoc (), która zwracałaby kolumny z kluczami reprezentującymi nazwy kolumn. Oczywiście można napisać własną funkcję, aby to zrobić, nie jest to nawet bardzo długie, ale miałem naprawdę trudności z jej napisaniem (dla niewierzących: jeśli wydaje ci się to łatwe, spróbuj sam i nie próbuj oszukiwać :))

mikrofon
źródło
4
Czy próbowałeś instrukcji? php.net/manual/en/mysqli-result.fetch-assoc.php
Do
2
Wdrażałem już dawno temu, ale tak, sprawdziłem instrukcję. Czy to działa z przygotowanymi wyciągami? Wątpię ...
Mike
2
W rzeczywistości ma dziwnie częściowe wsparcie. Możesz pobierać tablice w zwykłych zapytaniach, ale nie w zapytaniach sparametryzowanych: -!
Álvaro González
1
Dlaczego nie usunąć odpowiedzi, która jest oczywiście błędna?
Majid Fouladpour,
2
@MajidFouladpour - Odpowiedź nie jest oczywiście błędna . Po prostu brakuje jakiegoś kontekstu. Mysqli nie w pełni obsługuje pobieranie tablic asocjacyjnych.
Álvaro González