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?
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:
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.
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.
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.
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.
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.
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.
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.
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.
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:
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.
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).
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.
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ć :))
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.
Odpowiedzi:
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:
źródło
$mysqliResult->fetch_object("student");
?AS A BEST PRACTICE
to po prostu ... lol :) Google nie korzysta z pól publicznych, tylko akcesoria: google-styleguide.googlecode.com/svn/trunk/… .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.
źródło
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.
źródło
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.
źródło
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
PDOStatement
zmiennej w zmiennej należyunset()
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.źródło
Kolejną istotną (dobrą) różnicą dotyczącą PDO jest to, że
PDO::quote()
metoda ta automatycznie dodaje otaczające cytaty, podczas gdymysqli::real_escape_string()
(i podobne) nie:źródło
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
źródło
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.
źródło
insert
s - prawie równy,select
s - 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żytkowaniaPDO
przeważają nad wydajnością.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.
źródło
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:
(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
nie mają istotnego znaczenia.
Jednocześnie w obu tych interfejsach API brakuje niektórych naprawdę ważnych funkcji , takich jak
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.
źródło
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 sekundySHOW TABLE STATUS" -> mysqli()
szybciej o ~ 2,3 sekundySELECT * FROM users" -> mysqli()
szybciej o ~ 33 sekundUwaga: 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).
źródło
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')
.). MySQLifetch_object()
zwróci tylkostdClass
obiekt.źródło
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ć :))
źródło