Không bao giờ làm trong mã những gì bạn có thể làm cho máy chủ SQL làm tốt cho bạn. Đây có phải là một công thức cho một thiết kế xấu?


204

Đó là một ý tưởng tôi đã nghe lặp đi lặp lại ở một số nơi. Một số ít nhiều thừa nhận rằng một khi cố gắng giải quyết vấn đề hoàn toàn bằng SQL vượt quá một mức độ phức tạp nhất định, bạn thực sự nên xử lý nó bằng mã.

Logic đằng sau ý tưởng là trong phần lớn các trường hợp, công cụ cơ sở dữ liệu sẽ thực hiện công việc tốt hơn trong việc tìm ra cách hoàn thành nhiệm vụ hiệu quả nhất của bạn so với trong mã. Đặc biệt là khi nói đến những việc như làm cho kết quả có điều kiện đối với các hoạt động được thực hiện trên dữ liệu. Có thể cho rằng với các công cụ hiện đại có hiệu quả JIT'ing + lưu trữ phiên bản đã biên dịch của truy vấn của bạn, nó sẽ có ý nghĩa trên bề mặt.

Câu hỏi đặt ra là liệu có tận dụng công cụ cơ sở dữ liệu của bạn theo cách này vốn là thực tiễn thiết kế xấu (và tại sao). Các dòng trở nên mờ hơn nữa khi tất cả logic tồn tại bên trong cơ sở dữ liệu và bạn chỉ cần nhấn nó thông qua ORM.


60
Đây là một trong những câu nói phải được thực hiện chu đáo. Nó bị xóa sổ bất cứ khi nào người ta tìm thấy một kỹ sư khác đang thực hiện 'select * từ bảng' và sau đó lướt qua tập kết quả thay vì sử dụng mệnh đề where và chỉ định các cột. Nhưng nếu bạn đưa nó đi quá xa, bạn sẽ có một mớ hỗn độn khác.
Michael Kohne

154
Bắt đầu một cụm từ với "không bao giờ" hoặc "luôn luôn" gần như luôn luôn là một công thức cho một thiết kế xấu.
vsz

34
Mặc dù chắc chắn có thể cố gắng làm quá nhiều trong SQL, nhưng tôi có thể thành thật nói rằng trong 30 năm phát triển và tư vấn, tôi chưa bao giờ thấy một trường hợp nghiêm trọng thực sự nào về nó (một vài trường hợp nhỏ). Mặt khác, tôi đã thấy hàng trăm trường hợp nghiêm trọng của các nhà phát triển đang cố gắng thực hiện nhiều "mã" mà họ nên làm trong SQL. Và tôi vẫn thấy họ. Thường xuyên ...
RBarryYoung

2
@MrEdmundo Đưa nó đến meta.
ta.speot.is

4
Câu hỏi này là hai trong một - tôi nghĩ nó nên được chia. 1) Bao nhiêu nên được thực hiện trong SQL? 2) Bao nhiêu nên được thực hiện trong DBMS? Thủ tục lưu trữ rơi vào giữa. Tôi đã thấy toàn bộ các ứng dụng được mã hóa trong các thủ tục được lưu trữ.
Revierpost

Câu trả lời:


321

Theo cách nói của giáo dân:

Đây là những điều mà SQL được tạo ra để làm và, tin hay không, tôi đã thấy được thực hiện trong mã:

  • tham gia - mã hóa nó đòi hỏi thao tác mảng phức tạp
  • lọc dữ liệu (ở đâu) - mã hóa nó đòi hỏi phải chèn và xóa các mục trong danh sách
  • chọn cột - mã hóa nó yêu cầu danh sách nặng hoặc thao tác mảng
  • các hàm tổng hợp - mã hóa nó yêu cầu các mảng để giữ các giá trị và các trường hợp chuyển đổi phức tạp
  • tính toàn vẹn của khóa ngoại - mã hóa nó yêu cầu các truy vấn trước khi chèn và giả sử không ai sẽ sử dụng dữ liệu bên ngoài ứng dụng
  • tính toàn vẹn của khóa chính - mã hóa nó yêu cầu các truy vấn trước khi chèn và giả sử không ai sẽ sử dụng dữ liệu bên ngoài ứng dụng

Làm những việc này thay vì dựa vào SQL hoặc RDBMS dẫn đến việc viết hàng tấn mã không có giá trị gia tăng , nghĩa là có nhiều mã hơn để gỡ lỗi và duy trì. Và nó nguy hiểm giả định rằng cơ sở dữ liệu sẽ chỉ được truy cập thông qua ứng dụng.


88
+10000000000 để chỉ ra rằng nó nguy hiểm giả định mọi thứ sẽ chỉ xảy ra thông qua ứng dụng.
HLGEM

11
@skynorth Nó dẫn đến thiết kế cơ sở dữ liệu xấu. Xuống dòng bạn kết thúc với một cơ sở dữ liệu mà có thể chỉ được truy cập có ý nghĩa bởi ứng dụng mà do tất cả các bài chế biến nó.
Sirex

21
@skynorth Nếu bạn dựa vào mã để đảm bảo các khóa của bạn duy trì tính toàn vẹn, thì bạn đang loại bỏ một nguyên tắc cơ bản của RDBMS khỏi DB. Điều đó vô nghĩa, bởi vì sau đó mọi ứng dụng truy cập DB sẽ phải đảm bảo sao chép chính xác chức năng đó. Tại sao không để DB xử lý việc đó, vì đó là những gì nó được thiết kế cho. DB có thể ngăn chặn các khóa trùng lặp nguyên bản, ví dụ.
Butussy Butkus

10
đừng quên giao dịch!
Sklivvz

24
@skynorth: tl; dr: Các quy tắc giữ dữ liệu của bạn nhất quán nên được thực hiện trong cơ sở dữ liệu. tức là cho 99% các ứng dụng từng viết, dữ liệu (và do đó cơ sở dữ liệu) sống looooooooooong sau khi ứng dụng của bạn đã chết và biến mất. Tôi đã thấy điều này rất nhiều lần trong nhiều năm (Này, chúng ta cần triển khai một phiên bản trên Windows / iPhone / Android / bất cứ điều gì mới - bởi vì {chèn nền tảng cũ ở đây} đang chết dần, chúng ta ' sẽ lưu trữ hoặc cơ sở dữ liệu Oracle ở đây và tạo một giao diện người dùng mới ở đó ). Không có lý do cho xu hướng này dừng lại ngày hôm nay, hoặc bất cứ lúc nào sớm.
Nhị phân nhị phân

122

Tôi xin nói lại rằng "Không bao giờ làm những gì trong mã SQL Server có thể làm cho bạn tốt ".

Những thứ như thao tác chuỗi, hoạt động regex và như vậy tôi sẽ không làm trong SQL Server (chặn SQL CLR).

Ở trên có xu hướng nói về những thứ như - tham gia, thiết lập các hoạt động và truy vấn. Ý định đằng sau nó là ủy thác phần lớn việc nâng cấp cho SQL Server (mọi thứ rất tốt) và giảm lượng IO càng nhiều càng tốt (vì vậy hãy để SQL thực hiện tham gia và lọc xuống bằng một WHEREmệnh đề, trả lại nhiều tập dữ liệu nhỏ hơn so với khác).


27
Nếu mọi thứ SQL sẽ làm tốt hơn mã ứng dụng được đưa vào lớp SQL, thì có rất nhiều logic nghiệp vụ sẽ kết thúc trong cơ sở dữ liệu, tốt hơn hoặc xấu hơn. Tôi đã thấy điều này và vâng, hiệu suất là tuyệt vời. Nhưng may mắn thay, nhóm phát triển đều biết phát triển ứng dụng và SQL cực kỳ tốt vì biên giới giữa hai người trở nên rất vô định hình. Tôi sẽ không đề xuất đây là điểm khởi đầu mà là điểm kết thúc sau khi hệ thống trở nên rất phổ biến và hiệu suất suy giảm theo thời gian.
Jimmy Hoffa

3
Ngựa cho khóa học bẩm sinh guv?
StuperUser

28
@NathanLong Tôi không biết tại sao nhiều người vẫn nghĩ rằng bạn không thể kiểm soát SQL của mình. Lúc đầu, chúng tôi chỉ có tất cả các thủ tục lưu trữ / tập lệnh bảng / vv cần thiết để tạo cơ sở dữ liệu từ đầu trong kiểm soát nguồn, sau đó sử dụng các dự án cơ sở dữ liệu phòng thu trực quan. Nó hoạt động tốt mà không có các dự án và tốt hơn với họ. SQL cũng như mọi thứ có thể thay đổi khác cần thiết để tạo hệ thống của bạn phải nằm dưới sự kiểm soát phiên bản! Việc triển khai có thể được thực hiện với các công cụ tìm khác biệt cho hầu hết các RDBMS nếu bạn giữ các tập lệnh tạo của mình dưới sự kiểm soát phiên bản, không duy trì các tập lệnh diff sử dụng các công cụ
Jimmy Hoffa

3
Nếu SQL của bạn có hỗ trợ cho các hoạt động REGEX và thao tác chuỗi, thực hiện chúng trong SQL có thể là một lựa chọn tốt.
kevin cline

3
@NathanLong: nghĩ về nó như thế này, một bảng DB được xác định bởi một đoạn mã được viết trong tệp văn bản, cú pháp nằm dọc theo dòng "tạo bảng ...". Giờ đây, bạn có thể lưu trữ tệp văn bản đó trong bất kỳ SCM nào bạn thích, giống như nếu bạn có mã tạo bảng DB bằng ngôn ngữ ứng dụng yêu thích gọi bất kỳ API nào được yêu cầu và bạn sẽ lưu trữ tệp văn bản đó trong SCM của mình. Tôi nghĩ một vấn đề là một số người nghĩ DB bằng cách nào đó là những con thú ma thuật và họ chỉ biết viết mã VB (hoặc bất cứ điều gì) và vì vậy họ chỉ nghĩ theo ngôn ngữ ứng dụng mà họ biết.
gbjbaanb

47

Không bao giờ làm trong mã những gì bạn có thể làm cho máy chủ SQL làm tốt cho bạn (nhấn mạnh là của tôi)

Chìa khóa cho câu trả lời là bạn cần tìm kiếm SQL làm điều gì đó tốt, trái ngược với việc đơn giản là làm điều gì đó cho bạn. SQL là một ngôn ngữ mạnh mẽ đáng kinh ngạc. Cùng với các chức năng tích hợp, nó có khả năng có thể làm rất nhiều thứ. Tuy nhiên, thực tế là bạn có thể làm một cái gì đó trong SQL không phải là một lý do để thực sự làm điều đó trong SQL.

Tiêu chí cụ thể của tôi để đưa ra quyết định là xem xét số lượng dữ liệu bạn nhận được và số lượng chuyến đi khứ hồi: nếu bạn có thể cắt lượng dữ liệu bằng cách chuyển một tác vụ đến máy chủ, mà không tăng số lượng vòng chuyến đi, sau đó nhiệm vụ thuộc về máy chủ; nếu lượng dữ liệu vẫn giữ nguyên hoặc tăng mà không giảm đồng thời số lượng chuyến đi khứ hồi, thì nhiệm vụ thuộc về mã của bạn.

Hãy xem xét các ví dụ sau:

  • Bạn lưu trữ ngày sinh và bạn cần tính tuổi cho một nhóm người dùng. Bạn có thể yêu cầu máy chủ SQL thực hiện phép trừ hoặc bạn có thể thực hiện nó trong mã của mình. Số lượng các chuyến đi khứ hồi vẫn giữ nguyên và lượng dữ liệu được gửi lại cho bạn tăng lên. Do đó, một giải pháp dựa trên mã chiến thắng
  • Bạn lưu trữ ngày sinh và bạn cần tìm người dùng ở độ tuổi từ 20 đến 30. Bạn có thể tải lại tất cả người dùng trên máy khách, thực hiện phép trừ để tìm tuổi và sau đó thực hiện lọc, nhưng chuyển logic đến SQL Server sẽ giảm lượng dữ liệu mà không cần thêm một chuyến đi khứ hồi; do đó, giải pháp dựa trên SQL chiến thắng.

1
Khi tôi làm việc ở đâu đó logic kinh doanh trở nên vô định với SQL, chúng tôi không gặp khó khăn gì với nhiều chuyến đi khứ hồi; chúng tôi chỉ sử dụng nhiều bộ kết quả trong một chuyến đi khứ hồi, do đó quy tắc này bị phá vỡ ở đó, mặc dù tinh thần của quy tắc này khá tốt trong việc nhắm đến ý nghĩa vàng
Jimmy Hoffa

2
+1 đây là một câu trả lời tuyệt vời vì nó đưa ra các ví dụ cụ thể để hỗ trợ cả hai hướng.
Brandon

1
Trên ví dụ thứ hai của bạn. Bạn nói gì, Nếu kịch bản như dưới đây- Người dùng và bday là bộ nhớ cache và cho biết kích thước bản ghi nằm trong phạm vi 1000-2000. Không phải điều này nhanh hơn để làm điều này trong bộ nhớ, không yêu cầu cuộc gọi db vì dữ liệu được lưu trong bộ nhớ cache và do đó, giữa các hoạt động sql được tránh. Quá trình xử lý sẽ được lặp lại thông qua danh sách hơn 1000 người dùng trong bộ nhớ và tìm nơi xảy ra trận đấu. Điều này sẽ không nhanh hơn việc thực hiện trong db
user4677228

1
@ user4677228 Nhưng hãy thử nhân rộng :-p. Nếu mã của bạn phải quét tất cả dữ liệu để tính toán mọi lứa tuổi và kết quả mong muốn của bạn chỉ là có bao nhiêu người dùng ít nhất 20 và dưới 30 tuổi, thì bộ đệm sẽ không giúp bạn chút nào. Bạn vẫn sẽ kết thúc luồng toàn bộ bảng để khách hàng của bạn, nhưng máy chủ cơ sở dữ liệu có thể làm điều đó tất cả trong bộ nhớ / lưu trữ và cung cấp cho bạn một câu trả lời nhanh chóng cho dù khách hàng db được kết nối thông qua ổ cắm địa phương hoặc từ xa qua mạng nếu bạn chỉ muốn tính tuổi trong một WHEREmệnh đề.
binki

21

Nói tóm lại , sẽ là chính xác khi nói rằng: "Không bao giờ thực hiện các hoạt động cụ thể của cơ sở dữ liệu trong cơ sở mã của bạn" vì chúng được xử lý tốt hơn trong cơ sở dữ liệu của bạn.

Nhìn vào ví dụ của các hoạt động cơ sở thiết lập . Như bạn có thể biết, RDBMS được xây dựng để xử lý một hoạt động lưu trữ và thao tác dữ liệu phổ biến.

Ngoài ra, sự lựa chọn dự án của cơ sở dữ liệu đóng vai trò quan trọng . Có RDBMS (MS SQL, Oracle, v.v.) khác với cơ sở dữ liệu NoQuery như RavenDB.


Không bao giờ đặt các hoạt động thiết lập trong cơ sở mã của bạn có nghĩa là hoàn toàn mọi thứ được thực hiện trong LINQ cho các bộ sưu tập (select, sum, where, single) nên được thực hiện trong SQL và không phải trong ứng dụng của bạn, điều này sẽ đưa RẤT NHIỀU logic kinh doanh vào cơ sở dữ liệu của bạn.
Jimmy Hoffa

4
Những thứ mà bạn mô tả, không phải là mã khách hàng. Nó là một lớp Business, nơi bạn có thể có logic thao tác của riêng mình. Tuy nhiên, việc thực hiện logic này trên các bản ghi 1M + sẽ đánh trả bạn.
EL Yusubov

@JimmyHoffa: Điều đó không đúng, đôi khi bạn tạo ra thông tin nhất thời cần được xử lý với dữ liệu bạn đã có trên bộ nhớ ứng dụng. Linq làm việc kỳ diệu về điều đó.
Fabricio Araujo

@FovenioAraujo Tôi biết tại sao linq lại tuyệt vời, nhưng câu trả lời này nêu rõ Không bao giờ thực hiện các thao tác dựa trên mã ứng dụng, nếu bạn chưa bao giờ đặt thao tác trong mã ứng dụng, bạn sẽ không bao giờ sử dụng linq vì đó là toàn bộ mục đích của linq. Tôi đang đưa ra quan điểm rằng Không bao giờ thực hiện các thao tác thiết lập trong mã ứng dụng là một quy tắc tồi phải tuân theo
Jimmy Hoffa

@JimmyHoffa: Không, quy tắc nói "không bao giờ làm trong ứng dụng những gì RDBMS có thể làm tốt cho bạn". Và tôi đang nói về thông tin thoáng qua - không phải thông tin vẫn tồn tại trên cơ sở dữ liệu. Tôi đã làm việc trên các hệ thống trong đó, để hoàn thành các quy tắc kinh doanh, tôi cần xử lý mã. Tôi nhớ một quy tắc nghiệp vụ mà tôi đã có, sau khi xử lý nặng trên DB, xử lý bổ sung trên dữ liệu đó để tạo báo cáo (rất quan trọng). Tôi có thể sử dụng linq trên đó (nó đã được thực hiện trên Delphi.Net hiện không còn tồn tại). Nói cách khác, linq có thể được sử dụng ngay cả theo quy tắc đó.
Fabricio Araujo

13

Theo quy định, DB của bạn có nhiều thông tin để làm việc hơn ứng dụng của bạn và có thể thực hiện các hoạt động dữ liệu phổ biến hiệu quả hơn. Cơ sở dữ liệu của bạn duy trì các chỉ mục, ví dụ, trong khi ứng dụng của bạn sẽ phải lập chỉ mục kết quả tìm kiếm một cách nhanh chóng. Vì vậy, tất cả những thứ khác đều bằng nhau, khối lượng công việc tổng thể của bạn có thể được giảm bằng cách đẩy công việc vào cơ sở dữ liệu thay vì ứng dụng.

Nhưng khi quy mô sản phẩm của bạn, việc chia tỷ lệ ứng dụng của bạn trở nên dễ dàng hơn so với quy mô db của bạn. Trong các cài đặt lớn, không có gì lạ khi thấy các máy chủ ứng dụng vượt trội so với các máy chủ cơ sở dữ liệu theo hệ số từ 10 đến 1 hoặc nhiều hơn. Thêm nhiều máy chủ ứng dụng thường là một vấn đề đơn giản để nhân bản một máy chủ hiện có lên phần cứng mới. Việc thêm các máy chủ cơ sở dữ liệu mới, mặt khác, khó khăn hơn nhiều trong hầu hết các trường hợp.

Vì vậy, tại thời điểm này, thần chú trở thành bảo vệ cơ sở dữ liệu . Nó chỉ ra rằng bằng cách lưu trữ kết quả cơ sở dữ liệu vào memcachedhoặc bằng cách xếp hàng các bản cập nhật trong nhật ký phía ứng dụng hoặc bằng cách tìm nạp dữ liệu một lần và tính toán số liệu thống kê trong ứng dụng của bạn, bạn có thể giảm đáng kể khối lượng công việc cơ sở dữ liệu của mình, giúp bạn không phải dùng đến một cấu hình cụm DB thậm chí còn phức tạp và dễ vỡ hơn.


1
Tiền có thể giải quyết các vấn đề về khả năng mở rộng phần cứng, trong khi không có khoản tiền nào có thể giải quyết được sự phức tạp của phần mềm.
Tulains Córdova

3
@ user1598390 Thật vậy: Phần cứng rẻ, lập trình viên rất đắt . Tiền có thể giải quyết sự phức tạp của phần mềm. Tiền chi cho lập trình viên. Nhưng lưu ý rằng chúng ta không nói về mã sạch so với speghetti. Chúng ta đang nói về việc thực hiện công việc ở phía ứng dụng so với phía DB. Độ phức tạp của phần mềm chỉ liên quan với nhau, vì cả hai tùy chọn đều có thể tuân theo các nguyên tắc thiết kế tốt. Một câu hỏi tốt hơn là: " thiết kế nào có giá cao hơn? ".
tylerl

Một khi bạn có một cơ sở mã là hài hước và đầy chất béo, hầu hết nó làm công việc phi kinh doanh, điều duy nhất bạn có thể làm là mẹ của tất cả các kỹ sư tái chế, chi phí nhiều hơn phần cứng và có quá nhiều sự không chắc chắn, bên cạnh đó bạn sẽ luôn biết nơi để tìm phần cứng tốt, nhưng lập trình viên giỏi là một câu chuyện khác ... trong khi đó các đối thủ của bạn đang sử dụng thời gian của họ để cải thiện, thích nghi với thay đổi và làm cho khách hàng hài lòng.
Tulains Córdova

1
+1 vì là người duy nhất đề cập đến tỷ lệ trong câu trả lời của bạn.
Matt

Phần cứng rẻ, không còn nữa - trong trung tâm dữ liệu, điện và phần cứng chiếm tới 88% chi phí hoạt động (được trích dẫn bởi Microsoft), vì vậy, chi tiêu nhiều hơn cho các lập trình viên để viết mã hiệu quả là rất hiệu quả và sẽ cho đến khi chúng tôi nhận được không giới hạn và năng lượng nhiệt hạch giá rẻ.
gbjbaanb

12

Tôi nghĩ rằng nó sẽ là thiết kế kém để không sử dụng cơ sở dữ liệu cho những thứ nó có nghĩa là gì. Tôi chưa bao giờ thấy bất kỳ cơ sở dữ liệu nào trong đó các quy tắc được thi hành bên ngoài cơ sở dữ liệu có dữ liệu tốt. Và tôi đã xem xét hàng trăm cơ sở dữ liệu.

Vì vậy, những thứ phải được thực hiện trong cơ sở dữ liệu:

  • Kiểm toán (chỉ kiểm tra ứng dụng sẽ không theo dõi tất cả các thay đổi đối với cơ sở dữ liệu và do đó là vô giá trị).

  • Độ chính xác của dữ liệu bao gồm các giá trị mặc định, các ràng buộc và quy tắc khóa ngoài phải luôn được áp dụng cho tất cả dữ liệu. Tất cả dữ liệu không phải lúc nào cũng được thay đổi hoặc chèn thông qua một ứng dụng, có các sửa lỗi dữ liệu một lần, đặc biệt là các tập dữ liệu lớn không thực tế để thực hiện một bản ghi tại một thời điểm (vui lòng cập nhật 100.000 bản ghi này bị sai lệch thành trạng thái 1 khi chúng cần bị 2 do lỗi mã ứng dụng hoặc vui lòng cập nhật tất cả các bản ghi từ máy khách A sang máy khách B vì công ty B đã mua công ty A) và nhập dữ liệu và các ứng dụng khác có thể chạm vào cùng một cơ sở dữ liệu.

  • THAM GIA và nơi lọc mệnh đề (để giảm số lượng hồ sơ được gửi qua mạng)


6

"Tối ưu hóa sớm là gốc rễ của mọi tội lỗi (hầu hết, dù sao đi nữa) trong lập trình máy tính" - Donald Knuth

Cơ sở dữ liệu chính xác là như vậy; lớp dữ liệu của ứng dụng của bạn. Công việc của nó là cung cấp cho ứng dụng của bạn dữ liệu được yêu cầu và lưu trữ dữ liệu được cung cấp cho nó. Ứng dụng của bạn là nơi đặt mã thực sự hoạt động với dữ liệu; hiển thị nó, xác nhận nó, vv

Trong khi tình cảm trong dòng tiêu đề là đáng khâm phục, và chính xác đến một điểm (nitty-gritty lọc, lập dự án, nhóm vv nên trong rất nhiều trường hợp được để lại cho DB), một định nghĩa về "tốt" có thể là trong đặt hàng. Các tác vụ mà SQL Server có thể thực thi với mức hiệu năng cao là rất nhiều, nhưng các tác vụ mà bạn có thể chứng minhSQL Server thực hiện chính xác theo cách cô lập, lặp lại là rất ít. SQL Management Studio là một IDE cơ sở dữ liệu tuyệt vời (đặc biệt được cung cấp các tùy chọn khác mà tôi đã làm việc như TOAD), nhưng nó có những hạn chế, đầu tiên trong số đó là hầu hết mọi thứ bạn sử dụng để làm (hoặc bất kỳ mã thủ tục nào bạn thực thi theo định nghĩa DB bên dưới) là "tác dụng phụ" (thay đổi trạng thái nằm ngoài miền không gian bộ nhớ của quy trình của bạn). Ngoài ra, mã thủ tục trong SQL Server chỉ mới có, với các IDE và công cụ mới nhất, có thể được đo theo cách mã được quản lý có thể sử dụng số liệu bảo hiểm và phân tích đường dẫn (vì vậy bạn có thể chứng minh rằng câu lệnh cụ thể này gặp phải khi kiểm tra X , Y và Z và kiểm tra X được thiết kế để biến điều kiện thành đúng và thực thi nửa đó trong khi Y và Z thực thi "khác" . Đến lượt mình, giả sử bạn có một bài kiểm tra có thể thiết lập cơ sở dữ liệu với trạng thái bắt đầu cụ thể, thực thi mã thủ tục cơ sở dữ liệu thông qua một số hành động và khẳng định kết quả mong đợi.

Tất cả điều này là khó khăn và liên quan hơn nhiều so với giải pháp được cung cấp bởi hầu hết các lớp truy cập dữ liệu; giả sử lớp dữ liệu (và, đối với vấn đề đó, DAL) biết cách thực hiện công việc của họ khi được cung cấp đầu vào chính xác, và sau đó kiểm tra xem mã của bạn có cung cấp đầu vào chính xác không. Bằng cách giữ mã thủ tục như SP và kích hoạt ra khỏi DB và thay vào đó thực hiện các loại điều đó trong mã ứng dụng, mã ứng dụng cho biết dễ thực hiện hơn nhiều.


Đợi, đợi đã, cái gì? Làm thế nào bạn có được từ bằng chứng chính xác đến các bài kiểm tra, điều này có thể chứng minh rằng lỗi tồn tại nhưng không bao giờ có thể chứng minh rằng mã là chính xác?
Mason Wheeler

2
một thủ tục được lưu trữ không phải là mã thủ tục. SP là một truy vấn SQL được tính toán trước được lưu trữ và chạy bên trong DB. Nó không phải là mã ứng dụng.
gbjbaanb

1
Nếu SP bị giới hạn trong truy vấn SQL, thì bạn đã đúng. Nếu đó là T-SQL hoặc PL / SQL bao gồm các ngắt có điều kiện, các vòng lặp, con trỏ và / hoặc logic không truy vấn khác, bạn đã sai. Và rất nhiều SP, chức năng và trình kích hoạt trong DB trên khắp không gian ảo có các yếu tố bổ sung này.
KeithS

5

Một trong những điều mọi người dường như không nhận ra là việc thực hiện tất cả quá trình xử lý của bạn trên máy chủ SQL không nhất thiết phải tốt, bất kể ảnh hưởng đến chất lượng mã.

Ví dụ, nếu bạn cần lấy một số dữ liệu và sau đó tính toán một cái gì đó từ dữ liệu và sau đó lưu trữ dữ liệu đó trong cơ sở dữ liệu. Có hai sự lựa chọn:

  • Lấy dữ liệu vào ứng dụng của bạn, tính toán trong ứng dụng của bạn và sau đó gửi dữ liệu trở lại cơ sở dữ liệu
  • Tạo một thủ tục được lưu trữ hoặc tương tự để lấy dữ liệu, tính toán trên nó và sau đó lưu trữ tất cả từ một cuộc gọi đến máy chủ SQL.

Bạn có thể nghĩ rằng giải pháp thứ hai luôn nhanh nhất, nhưng điều này chắc chắn không đúng. Tôi bỏ qua ngay cả khi SQL không phù hợp với vấn đề (ví dụ như thao tác regex và chuỗi). Hãy giả vờ rằng bạn có SQL CLR hoặc một cái gì đó tương tự để có một ngôn ngữ mạnh mẽ trong cơ sở dữ liệu. Nếu bạn mất 1 giây để thực hiện một chuyến đi khứ hồi và lấy dữ liệu và 1 giây để lưu trữ dữ liệu đó, và sau đó 10 giây để thực hiện tính toán trên đó. Bạn đang làm sai nếu bạn đang làm tất cả trong cơ sở dữ liệu.

Chắc chắn, bạn cạo đi 2 giây. Tuy nhiên, bạn đã lãng phí 100% (ít nhất) một lõi CPU trên máy chủ cơ sở dữ liệu của mình trong 10 giây hay bạn đã lãng phí thời gian đó trên máy chủ web của mình?

Máy chủ web rất dễ mở rộng quy mô, mặt khác cơ sở dữ liệu cực kỳ tốn kém, đặc biệt là cơ sở dữ liệu SQL. Hầu hết thời gian, các máy chủ web cũng "không trạng thái" và có thể được thêm và xóa ngay lập tức mà không cần cấu hình bổ sung cho bất cứ thứ gì ngoại trừ bộ cân bằng tải.

Vì vậy, hãy suy nghĩ không chỉ về việc cạo 2 giây khỏi một thao tác, mà còn nghĩ về khả năng mở rộng. Tại sao lại lãng phí một tài nguyên đắt tiền như tài nguyên máy chủ cơ sở dữ liệu khi bạn có thể sử dụng tài nguyên máy chủ web rẻ hơn nhiều với tác động hiệu suất tương đối nhỏ


1
bạn cũng quên các chuyến đi mạng - bạn không thể mở rộng quy mô theo chiều ngang bằng cách thêm máy chủ mà không đạt được hiệu quả. Vì vậy, giảm tải dữ liệu bằng cách thêm một mệnh đề where là rõ ràng - nhưng các hoạt động sql khác sẽ không nhất thiết làm giảm hiệu suất. Quan điểm của bạn nói chung là đúng, nhưng không đến mức bạn coi DB là kho dữ liệu câm. Ứng dụng có khả năng mở rộng nhất mà tôi từng làm với các quy trình được lưu trữ đã sử dụng cho mỗi cuộc gọi dữ liệu (ngoại trừ 2 truy vấn phức tạp). Giải pháp thứ 3 là tốt nhất - "lưu trữ được lưu trữ để lấy dữ liệu cần thiết", không chắc bạn có ý định đó là 'tính toán' hay không.
gbjbaanb

4

Tôi muốn xem xét nó như SQL chỉ nên xử lý dữ liệu. Các quy tắc kinh doanh quyết định truy vấn có thể trông như thế nào có thể xảy ra trong mã. Regex hoặc xác nhận thông tin cần được thực hiện trong mã. SQL nên được để lại để tham gia bảng của bạn, truy vấn dữ liệu của bạn, chèn dữ liệu sạch, v.v.

Những gì được truyền vào SQL phải là dữ liệu sạch và SQL không thực sự cần biết gì hơn là cần lưu trữ, cập nhật, xóa hoặc lấy một cái gì đó. Tôi đã thấy quá nhiều nhà phát triển muốn ném logic kinh doanh và mã hóa vào SQL vì họ nghĩ dữ liệu là doanh nghiệp của họ. Tách logic của bạn khỏi dữ liệu của bạn và bạn sẽ thấy mã của mình trở nên sạch hơn và dễ quản lý hơn.

Chỉ cần 0,02 đô la của tôi mặc dù.


Tại sao bạn lại chạy regex hoặc xác thực trên dữ liệu đã có trong cơ sở dữ liệu? Các ràng buộc sẽ ngăn dữ liệu xấu không bao giờ đến đó và việc sử dụng regex có thể có nghĩa là bạn cần các cột hữu ích hơn ..
Brendan Long

Tôi đã không nói rằng tôi sẽ sử dụng regex hoặc xác nhận trên dữ liệu đến từ cơ sở dữ liệu. Tôi đoán tôi nên đã làm rõ rằng đó là cho dữ liệu đi đến cơ sở dữ liệu. Quan điểm của tôi là dữ liệu cần được làm sạch và xác nhận trước khi đến DAL.
Stanley Glass Jr

3

Nói chung, tôi đồng ý rằng mã phải kiểm soát logic nghiệp vụ và DB phải là hàm băm miễn phí logic. Nhưng đây là một số điểm truy cập:

Các ràng buộc chính, khóa ngoại và bắt buộc (không phải null) có thể được thi hành bằng mã. Những ràng buộc là logic kinh doanh. Họ có nên rời khỏi cơ sở dữ liệu vì họ sao chép mã nào có thể làm được không?

Các bên khác ngoài tầm kiểm soát của bạn có chạm vào cơ sở dữ liệu không? Nếu có các ràng buộc thực thi gần với dữ liệu là tốt. Quyền truy cập có thể bị hạn chế đối với dịch vụ web thực hiện logic, nhưng điều này giả định rằng bạn đã ở đó "trước tiên" và có quyền thực thi việc sử dụng dịch vụ cho các bên khác.

ORM của bạn có thực hiện chèn / cập nhật riêng cho từng đối tượng không? Nếu có, thì bạn sẽ gặp vấn đề nghiêm trọng về hiệu năng khi xử lý hàng loạt các tập dữ liệu lớn. Đặt hoạt động là cách để đi. Một ORM sẽ gặp khó khăn khi mô hình hóa chính xác tất cả các bộ đã tham gia mà bạn có thể thực hiện các thao tác trên đó.

Bạn có coi "lớp" là sự phân chia vật lý bởi các máy chủ hay sự phân chia logic? Chạy logic trên bất kỳ máy chủ nào về mặt lý thuyết vẫn có thể nằm dưới lớp logic của nó. Bạn có thể tổ chức phân tách bằng cách biên dịch thành các DLL khác nhau thay vì tách riêng các máy chủ. Điều này có thể làm tăng đáng kể thời gian phản hồi (nhưng hy sinh thông số) trong khi duy trì sự tách biệt các mối quan tâm. Một DLL phân tách sau đó có thể được chuyển đến các máy chủ khác mà không cần bản dựng mới để tăng thông lượng (với chi phí thời gian đáp ứng).


Tại sao các downvote?
mike30

5
Tôi chưa được đánh giá thấp, nhưng bất kỳ chuyên gia phân tích cơ sở dữ liệu nào cũng sẽ nói với bạn rằng việc xem xét cơ sở dữ liệu là hàm băm miễn phí logic là một ý tưởng rất tồi. Nó gây ra vấn đề toàn vẹn dữ liệu hoặc vấn đề hiệu suất hoặc cả hai.
HLGEM

1
@HLGEM. Câu trả lời mô tả lý do để giữ logic trong cơ sở dữ liệu hoặc ngồi trên máy chủ DB. Vẫn không giải thích nó.
mike30

Họ có thể đã không đến được các điểm như tôi đã làm, đó là lý do tại sao tôi không downvote.
HLGEM

3

Thành ngữ liên quan nhiều hơn đến việc tuân thủ các quy tắc kinh doanh, liên quan đến dữ liệu, cùng với các mối quan hệ (dữ liệu và cấu trúc và các mối quan hệ.) Nó không phải là một cửa cho mọi vấn đề nhưng nó giúp tránh mọi thứ như thủ công duy trì bộ đếm hồ sơ, duy trì mối quan hệ toàn vẹn thủ công, vv, nếu những thứ này có sẵn ở cấp cơ sở dữ liệu. Vì vậy, nếu có người khác xuất hiện và mở rộng chương trình hoặc viết chương trình khác tương tác với cơ sở dữ liệu, họ sẽ không phải tìm cách duy trì tính toàn vẹn của cơ sở dữ liệu từ mã trước đó. Trường hợp của bộ đếm hồ sơ được duy trì thủ công đặc biệt thích hợp khi người khác muốn tạo ra một chương trình mới để tương tác với cùng một cơ sở dữ liệu. Ngay cả khi chương trình mới được tạo có chính xác mã cho bộ đếm, chương trình gốc và chương trình mới chạy gần như cùng lúc có khả năng làm hỏng chương trình đó. Thậm chí còn có mã lấy ra các bản ghi và kiểm tra các điều kiện trước khi viết một bản ghi mới hoặc cập nhật (bằng mã hoặc dưới dạng truy vấn riêng), khi có thể, điều này thường có thể đạt được ngay trong câu lệnh chèn hoặc cập nhật. Tham nhũng dữ liệu một lần nữa có thể dẫn đến. Các công cụ cơ sở dữ liệu đảm bảo tính nguyên tử; một truy vấn cập nhật hoặc chèn với các điều kiện được đảm bảo chỉ ảnh hưởng đến các bản ghi đáp ứng các điều kiện và không có truy vấn bên ngoài nào có thể thay đổi nửa dữ liệu thông qua cập nhật của chúng tôi. Có nhiều trường hợp khác mà mã được sử dụng khi công cụ cơ sở dữ liệu sẽ phục vụ tốt hơn. Đó là tất cả về tính toàn vẹn dữ liệu và không phải về hiệu suất. Ngay cả mã cũng lấy ra các bản ghi và kiểm tra các điều kiện trước khi viết một bản ghi mới hoặc được cập nhật (bằng mã hoặc dưới dạng truy vấn riêng), khi có thể, điều này thường có thể đạt được ngay trong câu lệnh chèn hoặc cập nhật. Tham nhũng dữ liệu một lần nữa có thể dẫn đến. Các công cụ cơ sở dữ liệu đảm bảo tính nguyên tử; một truy vấn cập nhật hoặc chèn với các điều kiện được đảm bảo chỉ ảnh hưởng đến các bản ghi đáp ứng các điều kiện và không có truy vấn bên ngoài nào có thể thay đổi nửa dữ liệu thông qua cập nhật của chúng tôi. Có nhiều trường hợp khác mà mã được sử dụng khi công cụ cơ sở dữ liệu sẽ phục vụ tốt hơn. Đó là tất cả về tính toàn vẹn dữ liệu và không phải về hiệu suất. Ngay cả mã cũng lấy ra các bản ghi và kiểm tra các điều kiện trước khi viết một bản ghi mới hoặc được cập nhật (bằng mã hoặc dưới dạng truy vấn riêng), khi có thể, điều này thường có thể đạt được ngay trong câu lệnh chèn hoặc cập nhật. Tham nhũng dữ liệu một lần nữa có thể dẫn đến. Các công cụ cơ sở dữ liệu đảm bảo tính nguyên tử; một truy vấn cập nhật hoặc chèn với các điều kiện được đảm bảo chỉ ảnh hưởng đến các bản ghi đáp ứng các điều kiện và không có truy vấn bên ngoài nào có thể thay đổi nửa dữ liệu thông qua cập nhật của chúng tôi. Có nhiều trường hợp khác mà mã được sử dụng khi công cụ cơ sở dữ liệu sẽ phục vụ tốt hơn. Đó là tất cả về tính toàn vẹn dữ liệu và không phải về hiệu suất. Các công cụ cơ sở dữ liệu đảm bảo tính nguyên tử; một truy vấn cập nhật hoặc chèn với các điều kiện được đảm bảo chỉ ảnh hưởng đến các bản ghi đáp ứng các điều kiện và không có truy vấn bên ngoài nào có thể thay đổi nửa dữ liệu thông qua cập nhật của chúng tôi. Có nhiều trường hợp khác mà mã được sử dụng khi công cụ cơ sở dữ liệu sẽ phục vụ tốt hơn. Đó là tất cả về tính toàn vẹn dữ liệu và không phải về hiệu suất. Các công cụ cơ sở dữ liệu đảm bảo tính nguyên tử; một truy vấn cập nhật hoặc chèn với các điều kiện được đảm bảo chỉ ảnh hưởng đến các bản ghi đáp ứng các điều kiện và không có truy vấn bên ngoài nào có thể thay đổi nửa dữ liệu thông qua cập nhật của chúng tôi. Có nhiều trường hợp khác mà mã được sử dụng khi công cụ cơ sở dữ liệu sẽ phục vụ tốt hơn. Đó là tất cả về tính toàn vẹn dữ liệu và không phải về hiệu suất.

Vì vậy, nó thực sự là một thành ngữ hay quy tắc thiết kế tốt. Không có số lượng hiệu suất sẽ giúp trong một hệ thống với dữ liệu bị hỏng.


0

Như đã đề cập trước đó, mục tiêu là gửi và nhận càng ít càng tốt từ cơ sở dữ liệu vì các chuyến đi khứ hồi rất tốn thời gian. Gửi các thống kê SQL nhiều lần là một sự lãng phí thời gian, đặc biệt là trong các truy vấn phức tạp hơn.

Sử dụng các thủ tục được lưu trữ trong cơ sở dữ liệu cho phép các nhà phát triển tương tác với cơ sở dữ liệu như API, mà không phải lo lắng về lược đồ phức tạp ở mặt sau. Nó cũng làm giảm dữ liệu được gửi đến máy chủ vì chỉ có tên và một vài tham số được gửi. Trong kịch bản này, hầu hết logic của bussines vẫn có thể ở trong mã nhưng không ở dạng SQL. Mã về cơ bản sẽ chuẩn bị những gì sẽ được gửi hoặc yêu cầu từ cơ sở dữ liệu.


0

Có một vài điều cần nhớ:

  • Một cơ sở dữ liệu quan hệ cần đảm bảo tính toàn vẹn tham chiếu thông qua các khóa ngoại
  • Mở rộng một cơ sở dữ liệu có thể khó khăn và tốn kém. Mở rộng quy mô máy chủ web dễ dàng hơn nhiều chỉ bằng cách thêm nhiều máy chủ web. Hãy vui vẻ cố gắng để thêm sức mạnh máy chủ SQL.
  • Với C # và LINQ, bạn có thể thực hiện "tham gia" của mình và không cần thông qua mã để bạn có thể tận dụng tốt nhất cả hai thế giới trong nhiều trường hợp

0

"Tối ưu hóa sớm là gốc rễ của mọi tội lỗi" - Donald Knuth

Sử dụng công cụ thích hợp nhất cho công việc. Đối với tính toàn vẹn dữ liệu, đây thường là cơ sở dữ liệu. Đối với các quy tắc kinh doanh nâng cao, đây là một hệ thống dựa trên quy tắc như JBoss Drools. Để trực quan hóa dữ liệu, đây sẽ là một khung báo cáo. Vân vân.

Nếu bạn có bất kỳ vấn đề nào về hiệu năng, sau đó bạn nên xem liệu có dữ liệu nào có thể được lưu trong bộ nhớ cache hay không, liệu việc triển khai trong cơ sở dữ liệu sẽ nhanh hơn. Nhìn chung, chi phí mua thêm máy chủ hoặc thêm năng lượng đám mây sẽ thấp hơn nhiều so với chi phí bảo trì bổ sung và tác động của các lỗi bổ sung.

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.