Khi nào tôi nên sử dụng các thủ tục được lưu trữ?


19

Nếu tôi có tất cả logic nghiệp vụ của mình trong mã và sử dụng Entity Framework, trong trường hợp nào (nếu có), tôi có nên chuyển một số logic nghiệp vụ sang một thủ tục được lưu trữ, thay vì giữ tất cả trong mã?

Để rõ ràng, tôi có nghĩa là kết hợp với thiết lập hiện tại (logic nghiệp vụ trong mã), chứ không phải thay vì. Tôi đã thấy một số câu hỏi tương tự đang hỏi về ưu và nhược điểm của việc có tất cả logic kinh doanh trong các thủ tục được lưu trữ, nhưng tôi không tìm thấy nhiều về việc sử dụng các thủ tục được lưu trữ một cách tiết kiệm cho logic trường hợp cạnh, trong khi vẫn giữ phần còn lại của logic nghiệp vụ trong mã.

Nếu nó tạo ra sự khác biệt, tôi đang sử dụng MSSQL và Entity Framework.


Đây là những tình huống mà tôi đã sử dụng các thủ tục được lưu trữ trước đây:

  • Một báo cáo phức tạp mất vài phút để chạy (đây là một trang trong ứng dụng web). Tôi thấy tôi có thể viết SQL hiệu quả hơn nhiều (chỉ mất vài giây để chạy) so với những gì LINQ đang cung cấp.
  • Một ứng dụng web cần đọc và ghi vào một vài bảng trên cơ sở dữ liệu riêng biệt chứa nhiều thông tin nhạy cảm khác không liên quan đến ứng dụng. Thay vì cho phép nó truy cập vào mọi thứ, tôi đã sử dụng một thủ tục được lưu trữ chỉ thực hiện những gì cần thiết và chỉ trả về thông tin hạn chế. Sau đó, ứng dụng web chỉ có thể được cấp quyền truy cập vào quy trình được lưu trữ này mà không có quyền truy cập vào bất kỳ bảng nào, v.v.

Các bài viết khác tôi đã xem trước khi đặt câu hỏi này:


4
Cả hai tình huống của bạn là lý do hoàn toàn chính đáng để viết các thủ tục được lưu trữ. Bạn đang hỏi tại sao họ hợp pháp?
Robert Harvey

@RobertHarvey Tôi đã đảm bảo rằng chúng là hợp pháp và tìm kiếm các kịch bản hoặc lý do khác tại sao bạn có thể tạo một ngoại lệ và viết một thủ tục được lưu trữ thay vì giữ nó trong mã.
Amy Barrett

Bạn sẽ tạo một ngoại lệ và viết một thủ tục được lưu trữ khi bạn xác định rằng nó giải quyết vấn đề tốt hơn các kỹ thuật khác có sẵn cho bạn, đó chính xác là những gì bạn đã làm.
Robert Harvey

Câu trả lời:


10

Bạn có một vài kịch bản hoàn toàn tốt rồi.

Có rất nhiều lý do khác nữa. EF thực sự giỏi về CRUD và báo cáo khá thẳng về phía trước. Đôi khi, mặc dù, EF không phải là công cụ hoàn hảo. Một số lý do khác (kịch bản) để xem xét sử dụng các thủ tục được lưu trữ kết hợp với Entity Framework sẽ bao gồm:

  • Bạn có các đơn vị công việc phức tạp, có thể liên quan đến nhiều bảng, không thể được bao bọc trong giao dịch một cách dễ dàng bằng các tính năng của EF.
  • Cơ sở dữ liệu của bạn không hoạt động tốt với EF vì không tận dụng được tính toàn vẹn tham chiếu khai báo (ràng buộc khóa ngoài). Đây thường là một kịch bản xấu để tìm thấy chính bạn, nhưng đôi khi có những kịch bản phù hợp, chẳng hạn như cơ sở dữ liệu được sử dụng cho các quy trình ETL.
  • Bạn cần làm việc với dữ liệu vượt qua ranh giới máy chủ với các máy chủ được liên kết.
  • Bạn có các kịch bản truy xuất dữ liệu rất phức tạp trong đó cần có SQL "kim loại trần" để đảm bảo hiệu suất đầy đủ. Ví dụ: bạn có các phép nối phức tạp cần các gợi ý truy vấn để hoạt động tốt trong tình huống cụ thể của bạn.
  • Ứng dụng của bạn không có quyền CRUD đầy đủ trên một bảng nhưng ứng dụng của bạn có thể được phép chạy trong bối cảnh bảo mật mà máy chủ của bạn tin tưởng (ví dụ như nhận dạng ứng dụng, thay vì nhận dạng người dùng). Điều này có thể xuất hiện trong các tình huống trong đó các DBA hạn chế quyền truy cập bảng vào các procs được lưu trữ chỉ vì nó cho phép họ kiểm soát chi tiết hơn về việc ai có thể làm gì.

Tôi chắc chắn có nhiều hơn nữa ngoài những điều này. Cách để xác định con đường tốt nhất phía trước trong bất kỳ hoàn cảnh cụ thể nào là sử dụng một số ý nghĩa thông thường và tập trung vào mục tiêu chính, đó là viết mã chất lượng cao, dễ bảo trì. Chọn (các) công cụ cung cấp cho bạn kết quả này trong từng trường hợp.


Cảm ơn Joel, bạn đã đề cập đến một vài tình huống khác mà tôi chưa từng nghĩ đến.
Amy Barrett

Câu trả lời tốt đẹp. Tuy nhiên, tôi tự hỏi nếu bạn có nhiều người dùng kết nối với cơ sở dữ liệu và chạy các truy vấn phức tạp hoặc các thủ tục được lưu trữ, liệu bạn có kết thúc việc tải nhiều máy chủ cơ sở dữ liệu không?
Ripal Barot

1
@RipalBarot Không có gì phải bàn cãi khi khối lượng công việc càng nhiều (càng nhiều người dùng, truy vấn phức tạp hơn) thì càng có nhiều nhu cầu trên máy chủ cơ sở dữ liệu của bạn. Tuy nhiên, một điều cần lưu ý là việc sử dụng các thủ tục được lưu trữ thay vì ORM như Entity Framework thường có thể giảm bớt khối lượng công việc (một cách tương đối) vì các thủ tục được lưu trữ có thể có các kế hoạch truy vấn được biên dịch trước. Khi một truy vấn đến từ ORM, DBMS thường phải bắt đầu với việc tìm cách xử lý truy vấn. Khi bạn gọi một thủ tục được lưu trữ tương đương, cơ sở dữ liệu đã biết cách thực hiện nó một cách hiệu quả.
Joel Brown

2

Có lẽ nó có ý nghĩa, để xoay chuyển câu hỏi và tìm ra các giai đoạn mà chỉ các thủ tục được lưu trữ có thể làm, những gì bạn muốn đạt được. Có lẽ có những trường hợp thực sự sử dụng, nơi các thủ tục lưu trữ nổi bật.

Nếu nó tạo ra sự khác biệt, tôi đang sử dụng MSSQL và Entity Framework.

Kiến thức của tôi về EF còn hạn chế, nhưng theo như tôi có thể thấy, thì EF ( chỉ ) là một ORM như mọi thứ khác; và may mắn là có khả năng sử dụng SQL thô .

Nếu tôi lấy hai điểm chính của bạn:

Một báo cáo phức tạp mất vài phút để chạy (đây là một trang trong ứng dụng web). Tôi thấy tôi có thể viết SQL hiệu quả hơn nhiều (chỉ mất vài giây để chạy) so với những gì LINQ đang cung cấp.

LINQ / EF đã giảm, khi làm một báo cáo. Và như bạn nhận thấy, SQLnhanh hơn nhiều so với sử dụng ORM. Nhưng nói điều này có lợi cho các thủ tục được lưu trữ hay chỉ chống lại việc sử dụng ORM cho mọi thứ?

Vấn đề của bạn rõ ràng có thể giải quyết với SQL . Nếu truy vấn đó được lưu trữ và phiên bản được kiểm soát trong cơ sở mã của bạn - theo ví dụ của bạn - ít nhất là không có sự khác biệt .

Một ứng dụng web cần đọc và ghi vào một vài bảng trên cơ sở dữ liệu riêng biệt chứa nhiều thông tin nhạy cảm khác không liên quan đến ứng dụng. Thay vì cho phép nó truy cập vào mọi thứ, tôi đã sử dụng một thủ tục được lưu trữ chỉ thực hiện những gì cần thiết và chỉ trả về thông tin hạn chế. Sau đó, ứng dụng web chỉ có thể được cấp quyền truy cập vào quy trình được lưu trữ này mà không có quyền truy cập vào bất kỳ bảng nào, v.v.

Điều tương tự ở đây: một chuỗi kết nối đơn giản và CẬP NHẬT và vấn đề của bạn đã được thực hiện. Vấn đề này có thể được giải quyết ngay cả với ORM : chỉ cần sử dụng dịch vụ web trước DB khác và đạt được sự phân chia / cách ly tương tự .

Vì vậy, không có gì để xem ở đây.

Nhìn vào một số điểm mà những người khác đã thực hiện:

Bạn có các đơn vị công việc phức tạp, có thể liên quan đến nhiều bảng, không thể được bao bọc trong giao dịch một cách dễ dàng bằng các tính năng của EF.

Nhưng SQLcó thể làm điều đó. Không có phép thuật liên quan ở đây.

Cơ sở dữ liệu của bạn không chơi tốt với EF

Một lần nữa: Sử dụng EF khi thích hợp.

Bạn cần làm việc với dữ liệu vượt qua ranh giới máy chủ với các máy chủ được liên kết

Tôi không thấy, làm thế nào các thủ tục lưu trữ giúp đỡ. Vì vậy, tôi không thể thấy một lợi thế của các thủ tục được lưu trữ; nhưng có lẽ ai đó làm sáng tỏ điều đó

Bạn có các kịch bản truy xuất dữ liệu rất phức tạp trong đó cần có SQL "kim loại trần" để đảm bảo hiệu suất đầy đủ

Một lần nữa: "Ranh giới của EF ".

Ứng dụng của bạn không có quyền CRUD đầy đủ trên một bảng nhưng ứng dụng của bạn có thể được phép chạy trong bối cảnh bảo mật mà máy chủ của bạn tin tưởng

Được chứ. Tôi đi với một có thể .

Cho đến nay chỉ có một nửa điểm được thực hiện có lợi cho các thủ tục được lưu trữ.


Có lẽ có những cân nhắc về hiệu suất, trong đó có lợi cho các thủ tục được lưu trữ.

1) Lưu trữ các truy vấn có lợi ích của một cuộc gọi đơn giản đến thủ tục được lưu trữ, nó gói gọn sự phức tạp. Vì trình hoạch định truy vấn biết truy vấn, nên "tối ưu hóa" dễ dàng hơn. Nhưng việc lưu là với trình lập kế hoạch truy vấn tinh vi hiện tại _minimal.

Trên hết, ngay cả khi có một chi phí nhỏ khi sử dụng truy vấn ad hoc , nếu dữ liệu của bạn được cấu trúc tốt và được lập chỉ mục cẩn thận, cơ sở dữ liệu chỉ là nút cổ chai của ứng dụng của bạn. Vì vậy, ngay cả khi có một đồng bằng nhỏ, không thể bỏ qua việc xem xét các yếu tố khác.

2) Tuy nhiên, nó đã được lập luận để lưu trữ các truy vấn phức tạp trong DB. Có hai điều cần xem xét:

a) các truy vấn phức tạp sử dụng rất nhiều cơ sở hạ tầng DB, làm tăng thời gian tìm kiếm cho mọi truy vấn khác. Bạn không thể chạy song song nhiều truy vấn tốn kém . Điều này nói lên cả thủ tục lưu trữ procontra , nhưng chống lại các truy vấn phức tạp .

b) Nếu truy vấn mất thời gian, tại sao phải bận tâm với chiến thắng tốc độ nhỏ của một thủ tục được lưu trữ.

tl; dr

Không có gì nói trực tiếp chống lại các thủ tục được lưu trữ. Vì vậy, sử dụng các thủ tục được lưu trữ là được - nếu nó làm cho bạn hạnh phúc.

Nhưng mặt khác: tôi không thể tưởng tượng được một trường hợp sử dụng phù hợp có thể nói một cách dứt khoát .

Khi nào tôi nên sử dụng các thủ tục được lưu trữ?

Câu trả lời thích hợp là: Bất cứ khi nào bạn thích . Nhưng có những lựa chọn khác.


0

Đối với trường hợp cụ thể của bạn, vì bạn đang sử dụng khung thực thể, người ta nên xem xét sử dụng các thủ tục được lưu trữ khi khung thực thể không đáp ứng yêu cầu hoặc mối quan tâm.

Khung thực thể thực hiện một công việc tốt và hiệu suất sẽ gần hoặc bằng với việc sử dụng các thủ tục được lưu trữ. Bạn đã chọn khung thực thể vì bạn không muốn liên quan đến SQL và sẽ để khung tạo SQL cho bạn.

Nhưng có thể có một trường hợp cạnh mà khung thực thể bị thiếu và không thể đáp ứng nhu cầu của bạn. Trong trường hợp này, người ta sẽ viết SQL bằng tay bằng cách sử dụng một thủ tục được lưu trữ hoặc truy vấn được tham số hóa và sau đó sử dụng khung thực thể để gọi trực tiếp câu lệnh / câu lệnh SQL được lưu trữ đó.

Vì vậy, tôi sẽ không chuyển bất cứ thứ gì sang một thủ tục được lưu trữ trừ khi khung đang được sử dụng không thể đáp ứng yêu cầu.

Tôi nghĩ điều tồi tệ nhất có thể xảy ra là người ta chọn sử dụng khung thực thể và sau đó viết tất cả các thủ tục được lưu trữ. Bây giờ người ta có một lớp thêm mà không có giá trị.


100% đồng ý với đoạn cuối
Ewan

0

Có một nhu cầu kỹ thuật không phải là sự lựa chọn khả dĩ nhất. Các lập trình viên thích các công cụ của họ và thường thích nghi hơn trong việc giải quyết các vấn đề của họ với họ. Đưa logic vào một sproc sẽ là ngoại lệ. Nợ kỹ thuật và các nhà phát triển trong tương lai phải mất thời gian để làm việc với một ngoại lệ nên được xem xét. Có thể có một sự tăng hiệu năng trong RDBMS cụ thể của bạn, nó dễ thực hiện hơn trong một sproc hoặc thậm chí có thể là một đối tượng db khác như một khung nhìn được lập chỉ mục.

Sẽ có lúc bạn cần dữ liệu từ cơ sở dữ liệu và bạn không thể lấy nó từ mã ứng dụng của mình. Trong nhiều tình huống của công ty / doanh nghiệp lớn, nhu cầu kinh doanh có thể vượt quá khả năng của Bộ phận CNTT. Các công ty được mua và bán và các ứng dụng của họ đến và đi với họ. Các cơ quan quản lý và ngân hàng không quan tâm nếu bạn không thể xây dựng ứng dụng được mã hóa cao và đẹp mắt của mình. Họ có thể làm cho cuộc sống khó khăn cho doanh nghiệp, vì vậy bạn phải hoàn thành nó.

Tôi đã gặp phải tình huống trong đó các ứng dụng của bên thứ ba hoặc các công cụ viết báo cáo không cho phép bạn lấy mã của mình. Không có mã nguồn mở, không có API, không có giao diện web và không có dịch vụ. Điều duy nhất họ có là công cụ viết báo cáo đặc biệt của riêng họ chỉ hoạt động với các đối tượng cơ sở dữ liệu: bảng, dạng xem, sprocs, hàm do người dùng xác định, v.v. Bạn đặt logic bất cứ nơi nào bạn có thể nhận được.

Nếu bạn có một DBA rất giỏi trong việc viết các thủ tục được lưu trữ, bạn có thể tận dụng tài năng đó trong một số tình huống. Bạn có thể muốn kích hoạt một bản sao lưu từ ứng dụng của mình vì bạn sẽ thực hiện một thay đổi dữ liệu lớn, vậy tại sao không sử dụng những gì dba của bạn sử dụng?

Một số yêu cầu Ad hoc chỉ dễ dàng hơn để viết một Proc cho đến khi bạn có thể nhận được tất cả các chức năng trong ứng dụng của mình. Chúng tôi ghét nó. Chúng tôi đẩy lùi, nhưng chương trình phải tiếp tục.


0

Tôi sẽ khuyên bạn không nên đặt bất kỳ logic kinh doanh nào trong một thủ tục được lưu trữ. Tuy nhiên, có thể có một trường hợp (bạn đã liệt kê hai ví dụ tốt) trong đó nên đặt logic truy cập dữ liệu ở đó.

Nói chung, nếu bạn cảm thấy muốn sử dụng SP thì đó là một dấu hiệu (mùi mã) gợi ý rằng mô hình dữ liệu của bạn không phù hợp với nhu cầu của nó.

Chỉnh sửa: Khi các nhà phát triển hỏi tôi về logic truy cập dữ liệu / doanh nghiệp, tôi nói rằng logic nghiệp vụ là về cách dữ liệu ứng xử và tương tác, trong khi logic truy cập dữ liệu là về cách lưu trữ và truy xuất dữ liệu.

Ví dụ: Trong mô hình miền của bạn, bạn có thể có các thực thể "Sinh viên" và "Giáo viên", cả hai đều xuất phát từ "Người". (Không nói điều này được ưa thích, chỉ là một ví dụ). Điều này có thể được lưu trữ trong một cơ sở dữ liệu quan hệ dưới dạng một, hai hoặc ba bảng. Sự lựa chọn phụ thuộc vào số lượng thuộc tính họ chia sẻ và yêu cầu hiệu suất đọc / ghi.

Trong logic nghiệp vụ, việc các thực thể đó được lưu trữ như thế nào không quan trọng. (hoặc khi họ cư trú trong RDB). Logic truy cập dữ liệu là tất cả về cách chúng được lưu trữ vật lý.

Vì vậy, liên quan đến câu hỏi ban đầu: Nếu một thủ tục được lưu trữ làm cho việc lưu trữ và truy xuất dữ liệu hiệu quả hơn (hoặc mạnh mẽ hơn), bạn có một trường hợp. Nếu thủ tục được lưu trữ chỉ đơn thuần là áp đặt quy tắc mà tôi hợp lệ bất kể dữ liệu được lưu trữ như thế nào, hãy tránh nó. Nó làm cho mã của bạn được gắn chặt hơn với cơ sở dữ liệu.


2
Làm thế nào bạn sẽ xác định logic kinh doanh và logic truy cập dữ liệu ?
Amy Barrett


@RobertHarvey Cảm ơn các liên kết. Là lớp truy cập dữ liệu giống như logic truy cập dữ liệu? Tôi hỏi vì dường như không có nhiều logic thực tế liên quan đến lớp truy cập dữ liệu - chỉ là các thao tác CRUD đơn giản.
Amy Barrett

@AmyBarrett: Chà, đôi khi bạn viết các phương thức tùy chỉnh trong lớp Truy cập dữ liệu, vì vậy không phải lúc nào nó cũng là CRUD.
Robert Harvey

@RobertHarvey Những phương thức tùy chỉnh đó có thuộc về lớp logic nghiệp vụ không?
Amy Barrett

-4

Tôi nghĩ có ba vấn đề ở đây.

  1. Logic kinh doanh trong SQL là xấu. Ngay cả khi nó chạy cá nhân nhanh hơn, nó không mở rộng quy mô.

  2. Các XUÂN thông thường phải luôn được sử dụng cho tất cả các truy cập dữ liệu dưới dạng một lớp trừu tượng. Kích hoạt DBA để giới thiệu hiệu suất hoặc các thay đổi của trình dữ liệu khác mà không ảnh hưởng đến các ứng dụng tiêu thụ.

  3. EF không chơi đẹp với sprocs. Bạn sẽ mất rất nhiều tính năng 'tốt' và tăng năng suất bằng cách chuyển khỏi thế hệ truy vấn động của Linq.

Vì vậy, lời khuyên chung của tôi sẽ là

  • Sử dụng các XUÂN cho tất cả các truy vấn SQL,

  • Đừng đặt logic kinh doanh hoặc bất kỳ loại vòng lặp nào trong đó,

  • Đừng sử dụng EF.


Bởi vì tất cả SQL chạy trên máy chủ db, bạn chỉ có thể mở rộng quy mô với các dbs bổ sung thay vì các hộp tính toán thêm.
Ewan

1
Tôi hiểu rồi. Nhưng sau đó, điểm số 1 hoàn toàn là về sự đánh đổi giữa hai vấn đề hiệu suất. Nhưng sẽ có lúc giải pháp SQL là một chiến thắng rõ ràng về mặt hiệu suất, vì vậy tôi không thấy nó có thể bị coi là "xấu" như thế nào trên cơ sở này.

1
nói rằng bạn có một dịch vụ web thực hiện một phép tính. Bạn có thể làm điều đó trong mã hoặc trong sql. nói sql nhanh hơn trong một thử nghiệm đầu đối với một phép tính. Nhưng khi dịch vụ được tối đa hóa cpu, nó rất rẻ và dễ dàng để thêm hộp thứ hai, thứ ba, thứ tư .. chạy dịch vụ web nhưng khó và tốn kém để thêm cơ sở dữ liệu sao chép thứ hai
Ewan

1
đó là một ví dụ về một kịch bản cụ thể trong đó SQL có thể là một thiết kế tồi do khả năng mở rộng. Nhưng ngay cả khi đó cũng không rõ ràng: nó phụ thuộc vào số lượng người dùng dự kiến, chi phí tương đối để thực hiện tính toán trong cơ sở dữ liệu so với bên ngoài, v.v. Tất nhiên bạn đúng trong một số trường hợp, tôi chỉ không nghĩ đó là một quy tắc phổ quát.

3
Đây là lời khuyên tồi, nói chung. Có rất nhiều tùy chọn để truy cập dữ liệu có lợi thế hơn các thủ tục lưu trữ mã hóa bằng tay và cũng thực hiện tốt. Bạn có thể chạy sprocs trực tiếp từ EF; trong thực tế, bạn có thể chạy bất kỳ truy vấn sql trực tiếp từ EF. Một số logic nghiệp vụ chạy tốt hơn trên máy chủ cơ sở dữ liệu, vì vậy bạn không thể nói rõ rằng nó bị cấm ở đó. Ánh xạ đối tượng quan hệ là một công cụ 80%; chúng không bao giờ có nghĩa là thay thế hoàn toàn các quy trình truy cập dữ liệu của bạn. Sử dụng các thủ tục được lưu trữ cho những gì chúng được sử dụng cho: 20% mà ORM không hoạt động tốt.
Robert Harvey
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.