Sự khác biệt giữa ORM và trình tạo truy vấn là gì?

Trong bài đăng trên blog cổ điển năm 2006 The Vietnam of Computer Science, Ted Neward ví việc sử dụng các công cụ lập bản đồ quan hệ đối tượng với sự tham gia của Mỹ vào Việt Nam

Neward so sánh việc sử dụng các thư viện ORM với việc tham gia chiến tranh Việt Nam. Anh ấy lập luận rằng chắc chắn bạn sẽ rơi vào một tình huống khó khăn mà khó có thể giải thoát bản thân khỏi nó. Chuyển từ ORM của bạn sang sử dụng SQL thô sẽ chậm và khó khăn, giống như rút khỏi Việt Nam

Sự tương tự này gây cho tôi một chút kỳ lạ. Khi rút khỏi Việt Nam, U. S. và các đồng minh thoát khỏi xung đột và áp dụng chính sách không can thiệp vào công việc chính trị của Việt Nam. Nhưng khi nói đến SQL vs. ORM, không có cách nào để thoát khỏi xung đột. Nếu bạn đang sử dụng cơ sở dữ liệu quan hệ, bạn có thể sử dụng ORM hoặc bạn sử dụng SQL; . Né tránh các ORM cho SQL thô không giống với việc rút khỏi Việt Nam; . (Này, đó không phải là sự tương tự của tôi. )

“Việt Nam của khoa học máy tính” thực sự là cuộc tranh luận về SQL và ORM. Đó là một cuộc chiến ý thức hệ đã diễn ra ác liệt trong nhiều thập kỷ, mọi người phải đứng về một bên và không ai thắng

Cách duy nhất để chấm dứt một cuộc xung đột dai dẳng như vậy là điều chỉnh lại toàn bộ cuộc tranh luận. Chúng tôi cần một tùy chọn thứ ba kết hợp các điểm mạnh của ORM và SQL mà không có điểm yếu nào của chúng. Nhưng những điểm mạnh và điểm yếu này là gì?

Tôi đã chia nhỏ cuộc tranh luận thành một số điểm thảo luận chính;

  • biểu diễn giản đồ

  • di cư

  • Cú pháp truy vấn

  • cấu trúc kết quả

  • Tích hợp ngôn ngữ

  • Hiệu suất

  • Quyền lực

Trong SQL, lược đồ của bạn được xác định bởi tập hợp tất cả các lệnh của ngôn ngữ định nghĩa dữ liệu (DDL) (e. g.

class Person {
  name: string
}

class BlogPost {
  title: string
  author: Person
}
3) đã được thực thi đối với cơ sở dữ liệu của bạn. Thông thường, các lệnh DDL này được biểu diễn dưới dạng một tập hợp các tệp di chuyển được sắp xếp có thể được áp dụng dần dần khi lược đồ phát triển. Một số hương vị SQL tự động theo dõi lịch sử của tất cả các lệnh DDL;

CREATE TABLE persons (
  id uuid DEFAULT uuid_generate_v4() UNIQUE,
  name text NOT NULL
);
CREATE TABLE blog_posts (
  id uuid DEFAULT uuid_generate_v4() UNIQUE,
  title text NOT NULL,
  author_id uuid references persons(id)
);

Người dùng ORM cho rằng cách tiếp cận bắt buộc này đối với mô hình lược đồ không thân thiện với nhà phát triển vì không có văn bản nào mô tả lược đồ của bạn. Điều này gây khó khăn cho việc khái niệm hóa trạng thái lược đồ hiện tại

Thay vào đó, các ORM cung cấp một cách để viết lược đồ của bạn một cách khai báo, thông qua các định nghĩa lớp, cấu trúc dữ liệu, ngôn ngữ định nghĩa lược đồ tùy chỉnh hoặc một số cơ chế khác. Về cơ bản, biểu diễn này thường hướng đối tượng, nghĩa là một “mô hình” có thể chứa các tham chiếu rõ ràng đến các mô hình khác, chẳng hạn như

class Person {
  name: string
}

class BlogPost {
  title: string
  author: Person
}
4 trong ví dụ (mã giả) bên dưới

class Person {
  name: string
}

class BlogPost {
  title: string
  author: Person
}

Một bên về ORM

Nhiều bài phê bình cũ hơn về SQL (bao gồm cả tiểu luận Việt Nam, được viết năm 2006) giả định mô hình Bản ghi Hoạt động, trong đó các bảng SQL được ánh xạ tới các lớp tương ứng. Các thể hiện của các lớp này nhằm tương ứng và đồng bộ hóa trực tiếp với hàng cơ sở dữ liệu bên dưới. API trông giống như thế này

const user = new User('user_1234');
user.name = "Bobby Tables";
await user.save();

Điều này dẫn đến các vấn đề phức tạp xung quanh việc tìm nạp quá mức ("vấn đề đối tượng một phần" của Neward) và nhận dạng đối tượng. Tuy nhiên, những vấn đề này là cụ thể đối với các ngôn ngữ hướng đối tượng nghiêm ngặt, trong đó tất cả các đối tượng phải là một thể hiện của một lớp. Neward giải quyết vấn đề này

Lưu ý rằng một số ngôn ngữ dựa trên đối tượng, chẳng hạn như ECMAScript, xem các đối tượng khác với ngôn ngữ dựa trên lớp, chẳng hạn như Java hoặc C# hoặc C++, và kết quả là hoàn toàn có thể trả về các đối tượng chứa số lượng trường khác nhau. Điều đó nói rằng…cho đến khi những ngôn ngữ như vậy trở nên phổ biến, cuộc thảo luận như vậy vẫn nằm ngoài lĩnh vực của bài tiểu luận này

Chà, thật công bằng khi nói JavaScript và Python hiện đang phổ biến. Bài đăng này chủ yếu được viết với các ORM JavaScript và Python hiện đại. Nói chung, những thư viện này

  • tuân theo mẫu trình ánh xạ dữ liệu, trong đó chúng trả về các cấu trúc dữ liệu “đơn giản” thay vì các thể hiện của lớp;

  • cung cấp một API nhiều chức năng hơn;

  • phụ thuộc rộng rãi vào đối tượng/từ điển trong API của họ cho những thứ như lựa chọn trường;

await User.update('user_1234', {
  name: "Bobby Tables"
});

Cách tiếp cận mô hình khai báo đặt ra câu hỏi. ORM có phải là nguồn sự thật duy nhất cho thông tin lược đồ không?

  • Nếu không, thì bạn gặp vấn đề về lược đồ kép. Bạn phải giữ cho định nghĩa ORM của mình đồng bộ với lược đồ của cơ sở dữ liệu bên dưới, lược đồ này có lẽ đã được sửa đổi bằng một công cụ di chuyển SQL khác. Điều này vi phạm nguyên tắc DRY và tăng gánh nặng bảo trì

  • Nếu vậy, thì ORM phải cung cấp cơ chế di chuyển. một cách để tuyến tính hóa quá trình phát triển của các mô hình lược đồ thành một loạt các bước di chuyển bắt buộc (thường là các tập lệnh DDL). Về mặt kỹ thuật, điều này cũng vi phạm nguyên tắc DRY, vì cùng một lược đồ được biểu diễn ở cả dạng khai báo và mệnh lệnh (DDL), mặc dù đây là một vùng màu xám, vì DDL thường được tạo tự động

    Người dùng SQL cho rằng các hệ thống di chuyển được tạo tự động này dễ bị lỗi, không xử lý đúng các thay đổi phức tạp như đổi tên và hiếm khi hỗ trợ di chuyển dữ liệu trong các tình huống cần thiết. Viết tay logic di chuyển SQL đơn giản và an toàn hơn

ORM đơn giản hóa trải nghiệm tương tác với cơ sở dữ liệu; . SQL có một đường cong học tập dốc, vì một số lý do

  • Đó là một ngôn ngữ rộng lớn với hàng trăm từ khóa, quy tắc ngữ pháp và các loại câu lệnh

  • Do bề mặt API lớn, có nhiều điểm không nhất quán và các trường hợp cạnh (ví dụ: cách xử lý của

    class Person {
      name: string
    }
    
    class BlogPost {
      title: string
      author: Person
    }
    5)

  • Thứ tự mệnh đề của nó là bất ngờ, đặc biệt là thực tế là

    class Person {
      name: string
    }
    
    class BlogPost {
      title: string
      author: Person
    }
    0 đứng trước
    class Person {
      name: string
    }
    
    class BlogPost {
      title: string
      author: Person
    }
    1

  • Nhìn chung, SQL và mô hình quan hệ có vẻ xa lạ với các lập trình viên đã quen suy nghĩ về các vấn đề theo cách hướng đối tượng

Mặt khác, bạn chỉ phải học nó một lần. SQL là một kỹ năng có thể chuyển giao phần lớn, vì SQL là ngôn ngữ truy vấn phổ quát;

Ngược lại, không có hai API ORM nào giống nhau. Chúng cung cấp các cách không phải bản địa, dành riêng cho ngôn ngữ để lập mô hình lược đồ của bạn và viết các truy vấn. Bạn cần tìm hiểu một API mới bất cứ khi nào bạn chuyển sang ORM-du-jour mới. Ngoài ra, khi ứng dụng của bạn trở nên phức tạp hơn, bạn có thể sẽ đạt đến giới hạn về những gì ORM của bạn có thể đại diện, trong trường hợp đó, bạn sẽ cần quay lại SQL.

Tất cả các truy vấn SQL trả về một danh sách các bộ có giá trị vô hướng, ngay cả khi

class Person {
  name: string
}

class BlogPost {
  title: string
  author: Person
}
2 và
class Person {
  name: string
}

class BlogPost {
  title: string
  author: Person
}
3 từ các bảng được tham chiếu

________số 8

name     | post_title
-------------------------------------------------
"Anakin" | "Why I don't like sand"
"Anakin" | "One weird trick to surviving lava"
"Anakin" | "I've got a bad feeling about this"

Để làm cho kết quả được khách hàng sử dụng dễ dàng hơn, thông thường sẽ định dạng lại kết quả thành một đối tượng/từ điển có cấu trúc, đưa độ phức tạp vào logic ứng dụng

Có thể thực hiện tổng hợp và lồng JSON trong một số cơ sở dữ liệu SQL hiện đại, nhưng các cơ chế này không nhất quán, dài dòng và tẻ nhạt

Ngược lại, các ORM cung cấp một API hướng đối tượng để tìm nạp lồng nhau trả về một đối tượng có cấu trúc hữu ích hơn ngay lập tức so với “mảng các mảng” của SQL

class Person {
  name: string
}

class BlogPost {
  title: string
  author: Person
}
0

ORM cung cấp API mã đầu tiên để thể hiện các truy vấn, trong khi các truy vấn SQL thô thường được thể hiện dưới dạng các chuỗi đơn giản. Các chuỗi truy vấn này thường ngắn gọn hơn hoạt động ORM tương đương và cho phép các truy vấn được biểu diễn theo cách không phụ thuộc vào ngôn ngữ

Mặt khác, API ORM có thể được hưởng lợi từ chức năng của ngôn ngữ lập trình, tô sáng cú pháp, tự động hoàn thành, tự động định dạng và các công cụ khác ngày càng phổ biến trong môi trường nhà phát triển hiện đại

Nhưng có lẽ điều cần xem xét quan trọng nhất là khả năng ORM cung cấp kết quả truy vấn được nhập đầy đủ bên trong các ngôn ngữ được nhập tĩnh như TypeScript. Nếu không có ORM, người dùng phải viết cả truy vấn SQL và chữ ký loại dự kiến ​​của nó và đồng bộ hóa chúng theo cách thủ công. Điều này vi phạm nguyên tắc DRY và tăng gánh nặng bảo trì cho nhà phát triển

Vì các ORM thường thực thi các truy vấn SQL bí mật, nên chúng chỉ có thể hy vọng phù hợp với hiệu suất của một truy vấn SQL được tối ưu hóa tương đương;

Các hoạt động tìm nạp lồng nhau thường được chia thành một tập hợp các truy vấn SQL được thực thi tuần tự đơn giản hơn. Điều này đòi hỏi một số yêu cầu khứ hồi tới cơ sở dữ liệu;

Mặt khác, một cách tiếp cận ngây thơ để viết các truy vấn có tính kết nối cao (JOIN-heavy) trong SQL sẽ dẫn đến một vụ nổ cartesian trong tập kết quả (AKA là “quả bom tham gia”) có thể ảnh hưởng nghiêm trọng đến hiệu suất

ORM cung cấp một bộ chức năng CRUD giới hạn. truy vấn đơn giản, truy vấn lồng nhau, khả năng lọc theo một số nhóm toán tử giới hạn, đột biến lồng nhau, chèn, cập nhật và xóa. Các tùy chọn nâng cao có thể hỗ trợ upserts, tập hợp cơ bản và nhóm

Ngược lại, SQL là một ngôn ngữ truy vấn chính thức hỗ trợ một thư viện đầy đủ các hàm và toán tử, thuộc tính được tính toán, truy vấn con, hàm cửa sổ, nhóm nâng cao và truy vấn phân tích, thao tác chuyển đổi kiểu, thao tác thiết lập như

class Person {
  name: string
}

class BlogPost {
  title: string
  author: Person
}
4 và
class Person {
  name: string
}

class BlogPost {
  title: string
  author: Person
}
5, biểu thức bảng thông thường

Và đó chỉ là ngôn ngữ truy vấn; . Chúng có một hệ thống kiểu phong phú bao gồm các kiểu dữ liệu chuỗi, boolean, số, hình học, tiền tệ, thời gian và địa lý, cùng với các thuộc tính được tính toán, thủ tục được lưu trữ, chế độ xem cơ sở dữ liệu, trình kích hoạt, v.v.

ORM có phải là trình tạo truy vấn không?

Trình tạo truy vấn của ORM cung cấp giao diện thông thạo dễ sử dụng để tạo và chạy truy vấn.

Trình tạo truy vấn laravel có phải là ORM không?

Ứng dụng web luôn cần tương tác với cơ sở dữ liệu và Laravel làm cho nhiệm vụ này trở nên dễ dàng. Một vài công cụ làm cho Laravel trở thành một framework tuyệt vời là việc bao gồm “Trình tạo truy vấn và ORM Eloquent” .

Trình tạo truy vấn là gì?

Trình tạo truy vấn được được thiết kế để nâng cao năng suất và đơn giản hóa các tác vụ xây dựng truy vấn SQL . Trình tạo truy vấn cung cấp giao diện người dùng đồ họa để tạo truy vấn SQL. Bạn có thể kéo và thả nhiều bảng, dạng xem và cột của chúng vào công cụ thiết kế trực quan để tạo câu lệnh SQL.

Cái nào tốt hơn ORM hoặc truy vấn bình thường?

ORM và SQL là hai công cụ có sẵn mà các nhà phát triển web có thể sử dụng trong quản lý cơ sở dữ liệu. Khi so sánh chúng, SQL có khả năng quản lý thực tế cao hơn ORM . Vì ORM có mức độ trừu tượng cao hơn và phức tạp hơn SQL, nên cần ít quản lý thực hành hơn; .