mysqli hoặc PDO - những ưu và nhược điểm là gì? [đóng cửa]


342

Ở vị trí của chúng tôi, chúng tôi phân chia giữa việc sử dụng mysqli và PDO cho những thứ như báo cáo đã chuẩn bị và hỗ trợ giao dịch. Một số dự án sử dụng một, một số khác. Có rất ít khả năng thực tế của chúng tôi từng chuyển sang một RDBMS khác.

Tôi thích PDO vì một lý do duy nhất là nó cho phép các tham số được đặt tên cho các câu lệnh được chuẩn bị, và theo như tôi biết thì mysqli thì không.

Có bất kỳ ưu và nhược điểm nào khác khi chọn cái này làm tiêu chuẩn khác khi chúng tôi hợp nhất các dự án của chúng tôi để sử dụng chỉ một cách tiếp cận?


5
Bài viết này sẽ giúp chọn cái nào để sử dụng. Nếu bạn xem xét hiệu suất, điều này có thể giúp bạn chọn.
ravi404

3
Thật buồn cười khi có nhiều người đã ủng hộ và đánh dấu sao một câu hỏi "không mang tính xây dựng". Vấn đề là, toàn bộ chủ đề rất mang tính xây dựng - có lẽ người điều hành nên tính đến điều này khi đánh giá liệu một câu hỏi có phải là xây dựng hay không?
tuyên bố

@marlar Tôi rất đồng ý với bạn! Đây thực sự là vấn đề lớn nhất trên StackOverflow. Những câu hỏi / thảo luận xuất sắc luôn bị đóng cửa.
Sliq

Câu trả lời:


243

Chà, bạn có thể tranh luận với khía cạnh hướng đối tượng, các tuyên bố đã chuẩn bị, thực tế là nó trở thành một tiêu chuẩn, v.v. Nhưng tôi biết rằng hầu hết thời gian, thuyết phục ai đó làm việc tốt hơn với tính năng sát thủ. Vì vậy, nó là:

Một điều thực sự thú vị với PDO là bạn có thể tìm nạp dữ liệu, tự động đưa dữ liệu vào một đối tượng. Nếu bạn không muốn sử dụng ORM (vì đó chỉ là một tập lệnh nhanh) nhưng bạn thích lập bản đồ đối tượng, điều đó thật sự rất tuyệt:

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
Có sự khác biệt giữa ở trên và $mysqliResult->fetch_object("student");?
Andy Fleming

2
@ e-satis không, tôi dùng PHP. Các trường công cộng vi phạm đóng gói, vì vậy, đó AS A BEST PRACTICEchỉ là ... lol :) Google không sử dụng các trường công khai, chỉ có những người truy cập: google-styleguide.googlecode.com/svn/trunk/ .
OZ_

6
@ e-satis: Xin lỗi vì đã nhảy vào nhưng getters và setters là cần thiết nếu bạn muốn kiểm soát những gì xảy ra khi các biến được thay đổi. Nếu không, bạn đơn giản không thể đảm bảo trạng thái bên trong của đối tượng của bạn (điều này đặc biệt là vấn đề nếu bạn có một đối tượng khác bên trong). Điều này là hoàn toàn độc lập ngôn ngữ. @OZ_: Làm dễ lên. Những lời chỉ trích cá nhân sẽ chỉ đưa người khác vào thế phòng thủ.
James P.

2
@monadic: Đồng ý. Đóng gói tất nhiên là một đối số hợp lệ khi xử lý các thành phần cốt lõi, hoặc các đối tượng phức tạp, v.v., tuy nhiên, như là các biểu diễn của các bản ghi mà nếu không thì sẽ là PGS-đọc. mảng, điều này được chấp nhận. Hơn nữa, nó cho phép kiểm tra loại dễ dàng hơn khi hồ sơ trôi qua hệ thống.
Dan Lugg

15
@outis Tôi hy vọng tôi không thuộc thiểu số ở đây, nhưng tôi không cảm thấy câu trả lời nên được đánh giá về sự an toàn của họ đối với các nhà phát triển mới. Nghe có vẻ khắc nghiệt, nhưng đó là sự thật. Mục đích của câu trả lời trên SO không chỉ là cung cấp mã sao chép và dán mà còn cung cấp sự hiểu biết. Ví dụ, đây không phải là công việc của người trả lời để đảm bảo mọi lỗ hổng bảo mật hoặc lỗ hổng mẫu được bảo vệ, bởi vì hãy đối mặt với nó, ứng dụng mà mã được sao chép vào vốn khác với mọi ứng dụng khác sử dụng cùng một mã.
Mattygabe

57

Di chuyển một ứng dụng từ cơ sở dữ liệu này sang cơ sở dữ liệu khác không phổ biến lắm, nhưng sớm hay muộn bạn có thể thấy mình làm việc trên một dự án khác bằng RDBMS khác. Nếu bạn đang ở nhà với PDO thì ít nhất sẽ có một điều ít để học vào thời điểm đó.

Ngoài ra, tôi thấy API PDO trực quan hơn một chút và nó cảm thấy hướng đối tượng thực sự hơn. mysqli cảm thấy như nó chỉ là một API thủ tục đã được khách quan hóa, nếu bạn hiểu ý tôi là gì. Nói tóm lại, tôi thấy PDO dễ làm việc hơn, nhưng đó là điều tất nhiên.


25

Tôi đã bắt đầu sử dụng PDO vì theo tôi, hỗ trợ tuyên bố tốt hơn. Tôi đang sử dụng lớp truy cập dữ liệu ActiveRecord-esque và việc triển khai các câu lệnh được tạo động dễ dàng hơn nhiều. Liên kết tham số của MySQL phải được thực hiện trong một lệnh gọi hàm / phương thức duy nhất, vì vậy nếu bạn không biết cho đến khi chạy bao nhiêu tham số bạn muốn liên kết, bạn buộc phải sử dụng call_user_func_array()(tôi tin rằng đó là tên hàm đúng) cho các lựa chọn . Và quên đi ràng buộc kết quả năng động đơn giản.

Trên hết, tôi thích PDO vì đó là một mức độ trừu tượng rất hợp lý. Thật dễ dàng để sử dụng nó trong các hệ thống hoàn toàn trừu tượng, nơi bạn không muốn viết SQL, nhưng nó cũng giúp bạn dễ dàng sử dụng loại hệ thống truy vấn thuần túy, tối ưu hóa hơn hoặc để kết hợp và kết hợp cả hai.


2
Kết quả ràng buộc với các truy vấn được tạo động là có thể, chúng tôi làm điều đó tại các ứng dụng của chúng tôi. Tuy nhiên, đó là một nỗi đau rất lớn.
Pim Jager

17

PDO là tiêu chuẩn, đó là những gì hầu hết các nhà phát triển sẽ sử dụng. mysqli về cơ bản là một giải pháp bespoke cho một vấn đề cụ thể, nhưng nó có tất cả các vấn đề của các thư viện dành riêng cho DBMS khác. PDO là nơi tất cả những công việc khó khăn và suy nghĩ thông minh sẽ đi.


15

Đây là một điều khác cần ghi nhớ: Hiện tại (PHP 5.2) thư viện PDO bị lỗi . Nó chứa đầy những con bọ lạ. Ví dụ: trước khi lưu trữ một PDOStatementbiến, biến phải là unset()để tránh hàng tấn lỗi. Hầu hết trong số này đã được sửa trong PHP 5.3 và chúng sẽ được phát hành vào đầu năm 2009 trong PHP 5.3, có thể sẽ có nhiều lỗi khác. Bạn nên tập trung vào việc sử dụng PDO cho PHP 6.1 nếu bạn muốn một bản phát hành ổn định và sử dụng PDO cho PHP 5.3 nếu bạn muốn giúp đỡ cộng đồng.


2
Tôi nghĩ rằng những lợi ích mà PDO mang lại là đáng để hiểu và làm việc xung quanh các lỗi. Bản thân PHP có rất nhiều lỗi rất nghiêm trọng, một số lỗi mà chúng ta thậm chí không thể làm việc hiệu quả, nhưng nó mang lại nhiều lợi ích khiến chúng ta sử dụng nó thay vì các tùy chọn khác.
Brian Warshaw

11
Uhm, lạ thật, tôi chưa bao giờ gặp bất kỳ lỗi nào với PDO. Và tôi sử dụng nó rất nhiều.
NikiC

Mysqli cũng có lỗi. Tất cả các phần mềm đều có lỗi.
Bill Karwin

10

Một điểm khác biệt đáng chú ý (tốt) về PDO là PDO::quote()phương thức của nó tự động thêm các trích dẫn kèm theo, trong khi mysqli::real_escape_string()(và similars) không:

PDO :: quote () đặt các trích dẫn xung quanh chuỗi đầu vào (nếu cần) và thoát các ký tự đặc biệt trong chuỗi đầu vào, sử dụng kiểu trích dẫn phù hợp với trình điều khiển bên dưới.


8

PDO sẽ giúp mở rộng quy mô dễ dàng hơn rất nhiều nếu ứng dụng trang web / web của bạn thực sự trở thành như bạn có thể thiết lập các kết nối Master và Slave hàng ngày để phân phối tải trên cơ sở dữ liệu, cộng với PHP đang hướng tới PDO như một tiêu chuẩn.

Thông tin PDO

Mở rộng ứng dụng web


6

Về mặt tốc độ thực thi, MySQLi thắng, nhưng trừ khi bạn có một trình bao bọc tốt bằng MySQLi, các chức năng của nó xử lý các câu lệnh được chuẩn bị là rất tệ.

Vẫn còn những lỗi trong tôi, nhưng nếu có ai muốn nó, thì đây là .

Vì vậy, trong ngắn hạn, nếu bạn đang tìm kiếm một tốc độ tăng, thì MySQLi; nếu bạn muốn dễ sử dụng, thì PDO.


2
trong ý nghĩa của tốc độ, bạn có thể cho điểm chuẩn?
Julius F

8
Jonathen Robson đã thực hiện một so sánh tốc độ khá của hai người tại jonathanrobson.me/2010/06/mysqli-vs-pdo-benchmark . Tóm tắt: inserts - gần như bằng nhau, selects - mysqli nhanh hơn ~ 2,5% cho các câu lệnh chưa chuẩn bị / ~ 6,7% cho các câu lệnh được chuẩn bị. Cho dù mức phạt hiệu suất nhỏ như thế nào, các tính năng và tính linh hoạt của việc sử dụng PDOthường vượt trội hơn so với hiệu suất đạt được.
Adam

1
@Adam Cảm ơn bạn đã liên kết đến blog của tôi!
jnrbsn

@ daemonfire300 Điều này là đúng, không cần điểm chuẩn. PDO kết thúc thư viện mysqli. Tôi có lẽ sẽ trúng fan nếu ai đó có thể chứng minh rằng PDO nhanh hơn mysqli. :-D
Dyin

@jnrbsn bạn có đồng ý với Adam về những gì anh ấy nói không?
Basit

5

Cá nhân tôi sử dụng PDO, nhưng tôi nghĩ đó chủ yếu là một câu hỏi về sở thích.

PDO có một số tính năng giúp chống lại việc tiêm SQL (các câu lệnh đã chuẩn bị ), nhưng nếu bạn cẩn thận với SQL của mình, bạn cũng có thể đạt được điều đó với mysqli.

Chuyển sang cơ sở dữ liệu khác không phải là lý do để sử dụng PDO. Miễn là bạn không sử dụng "các tính năng SQL đặc biệt", bạn có thể chuyển từ DB này sang DB khác. Tuy nhiên, ngay sau khi bạn sử dụng ví dụ "CHỌN ... GIỚI HẠN 1", bạn không thể truy cập MS-SQL trong đó "CHỌN TOP 1 ...". Vì vậy, đây là vấn đề.


22
MySQLi đã chuẩn bị báo cáo.
Tháp

5

Chỉnh sửa câu trả lời.

Sau khi có một số kinh nghiệm với cả hai API này, tôi sẽ nói rằng có 2 tính năng cấp chặn chặn khiến mysqli không thể sử dụng được với các câu lệnh được chuẩn bị sẵn.
Họ đã được đề cập trong 2 câu trả lời xuất sắc (chưa được đánh giá thấp):

  1. Giá trị ràng buộc với số lượng giữ chỗ tùy ý
  2. Trả lại dữ liệu dưới dạng một mảng

(cả hai cũng được đề cập trong câu trả lời này )

Vì một số lý do, mysqli đã thất bại với cả hai.
Ngày nay, nó đã có một số cải tiến cho cái thứ hai ( get_result ), nhưng nó chỉ hoạt động trên các cài đặt mysqlnd, có nghĩa là bạn không thể dựa vào chức năng này trong các tập lệnh của mình.

Tuy nhiên, nó không có ràng buộc theo giá trị cho đến ngày nay.

Vì vậy, chỉ có một lựa chọn: PDO

Tất cả các lý do khác, chẳng hạn như

  • giữ chỗ được đặt tên (cú pháp đường này được đánh giá quá cao)
  • hỗ trợ cơ sở dữ liệu khác nhau (không ai thực sự từng sử dụng nó)
  • tìm nạp vào đối tượng (chỉ là cú pháp đường vô dụng)
  • chênh lệch tốc độ (không có)

không có tầm quan trọng đáng kể.

Đồng thời cả hai API này đều thiếu một số tính năng thực sự quan trọng , như

  • giữ chỗ định danh
  • giữ chỗ cho các kiểu dữ liệu phức tạp để làm cho ràng buộc động ít gây hại hơn
  • mã ứng dụng ngắn hơn.

Vì vậy, để đáp ứng nhu cầu thực tế , người ta phải tạo thư viện trừu tượng của riêng mình, dựa trên một trong các API này, triển khai các trình giữ chỗ được phân tích cú pháp thủ công. Trong trường hợp này tôi thích mysqli hơn, vì nó có mức độ trừu tượng ít hơn.


Cuối cùng cũng có người biết và không phủ nhận sự thật của cuộc sống ...
Ihsan

4

Trong tập lệnh chuẩn của tôi , mỗi phương thức được kiểm tra 10000 lần và sự khác biệt của tổng thời gian cho mỗi phương thức được in. Bạn nên làm điều này trên cấu hình của riêng bạn, tôi chắc chắn kết quả sẽ thay đổi!

Đây là kết quả của tôi:

  • " SELECT NULL" -> PGO()nhanh hơn ~ 0,35 giây
  • " SHOW TABLE STATUS" -> mysqli()nhanh hơn ~ 2,3 giây
  • " SELECT * FROM users" -> mysqli()nhanh hơn ~ 33 giây

Lưu ý: bằng cách sử dụng -> fetch_row () cho mysqli, tên cột không được thêm vào mảng, tôi không tìm thấy cách nào để làm điều đó trong PGO. Nhưng ngay cả khi tôi sử dụng -> fetch_array (), mysqli hơi chậm nhưng vẫn nhanh hơn PGO (ngoại trừ CHỌN NULL).


17
PGO là gì? Và nhanh hơn 33 giây ?! Tôi thấy điều đó thật khó tin ...
Alix Axel

3

Một điều PDO có là MySQLi không thực sự tôi thích là khả năng của PDO trả về kết quả dưới dạng một đối tượng của một loại lớp được chỉ định (ví dụ $pdo->fetchObject('MyClass')). MySQLi's fetch_object()sẽ chỉ trả về một stdClassđối tượng.


19
Trên thực tế, bạn có thể chỉ định một lớp theo cách thủ công: "object mysqli_result :: fetch_object ([chuỗi $ class_name [, mảng $ params]])". stdClass chỉ được sử dụng nếu bạn không chỉ định bất cứ điều gì.
Andrioid

-4

Có một điều cần ghi nhớ.

Mysqli không hỗ trợ hàm fetch_assoc () sẽ trả về các cột bằng các khóa biểu thị tên cột. Tất nhiên có thể viết chức năng của riêng bạn để làm điều đó, nó thậm chí không dài lắm, nhưng tôi đã rất khó khăn để viết nó (đối với những người không tin: nếu nó có vẻ dễ dàng với bạn, hãy tự mình thử một chút và đừng ' t gian lận :))


4
Bạn đã thử hướng dẫn chưa? php.net/manual/en/mysqli-result.fetch-assoc.php
Đến

2
Đã thực hiện lâu hơn trước đây, nhưng có tôi đã kiểm tra hướng dẫn. Nó làm việc với các báo cáo chuẩn bị? Tôi nghi ngờ ...
mike

2
Trên thực tế, nó có một phần hỗ trợ tò mò. Bạn có thể tìm nạp các mảng trong các truy vấn thông thường nhưng không phải trong các truy vấn được tham số hóa: -!
Álvaro González

1
Tại sao không xóa một câu trả lời rõ ràng là sai?
Majid fouadpour

2
@MajidFouladpour - Câu trả lời rõ ràng không sai . Nó chỉ thiếu một số bối cảnh. Mysqli không hỗ trợ đầy đủ truy xuất mảng kết hợp.
Álvaro González
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.