Thủ tục lưu trữ so với SQL nội tuyến


27

Tôi biết các thủ tục được lưu trữ có hiệu quả hơn thông qua đường dẫn thực thi (so với sql nội tuyến trong các ứng dụng). Tuy nhiên, khi bị ép, tôi không hiểu lắm về lý do tại sao.

Tôi muốn biết lý do kỹ thuật cho việc này (theo cách mà tôi có thể giải thích nó cho ai đó sau này).

Bất cứ ai có thể giúp tôi xây dựng một câu trả lời tốt?


1
Một truy vấn tham số đúng cách cũng tốt như một thủ tục được lưu trữ, từ quan điểm hiệu suất. Cả hai đều được biên dịch trước khi sử dụng lần đầu tiên, cả hai sẽ sử dụng lại kế hoạch thực hiện được lưu trong bộ nhớ cache cho các lần thực hiện tiếp theo, cả hai gói đều được lưu trong cùng một bộ đệm của gói và cả hai sẽ được xử lý cùng tên. Không có lợi ích hiệu năng cho một thủ tục được lưu trữ nữa, trong SQL Server ngày nay.
marc_s

@marc_s điều đó đúng nếu các truy vấn giống hệt nhau. Tuy nhiên như tôi đã chỉ ra trong câu trả lời của mình, có một số đặc điểm của truy vấn ad hoc có thể là vấn đề về hiệu suất ngay cả đối với các truy vấn có vẻ giống nhau.
Aaron Bertrand

Câu trả lời:


42

Tôi tin rằng tình cảm này đã đúng ở một thời điểm, nhưng không phải trong các phiên bản hiện tại của SQL Server. Toàn bộ vấn đề là ngày xưa các câu lệnh SQL ad hoc không thể được tối ưu hóa một cách chính xác vì SQL Server chỉ có thể tối ưu hóa / biên dịch ở cấp độ lô. Bây giờ chúng ta đã tối ưu hóa mức câu lệnh, do đó, một truy vấn được tham số hóa chính xác đến từ một ứng dụng có thể tận dụng cùng một kế hoạch thực hiện như truy vấn đó được nhúng trong một thủ tục được lưu trữ.

Tôi vẫn thích các thủ tục được lưu trữ từ phía DBA vì những lý do sau (và một vài trong số chúng có thể có tác động rất lớn đến hiệu suất):

  • Nếu tôi có nhiều ứng dụng sử dụng lại cùng một truy vấn, một quy trình được lưu trữ sẽ đóng gói logic đó, thay vì xả rác cùng một truy vấn ad hoc nhiều lần trong các cơ sở mã khác nhau. Các ứng dụng sử dụng lại các truy vấn tương tự cũng có thể bị lên kế hoạch phình to bộ đệm, trừ khi chúng được sao chép nguyên văn. Ngay cả sự khác biệt về trường hợp và khoảng trắng có thể dẫn đến nhiều phiên bản của cùng một gói được lưu trữ (lãng phí).
  • Tôi có thể kiểm tra và khắc phục sự cố những gì một truy vấn đang làm mà không cần truy cập vào mã nguồn ứng dụng hoặc chạy các dấu vết đắt tiền để xem chính xác những gì ứng dụng đang làm.
  • Tôi cũng có thể kiểm soát (và biết trước) ứng dụng nào có thể chạy, bảng nào có thể truy cập và trong bối cảnh nào, v.v. Nếu các nhà phát triển đang viết truy vấn đặc biệt trong ứng dụng của họ, họ sẽ phải hãy kéo tay áo tôi mỗi khi họ cần truy cập vào một cái bàn mà tôi không biết hoặc không thể dự đoán được, hoặc nếu tôi ít trách nhiệm / say mê và / hoặc có ý thức bảo mật, tôi sẽ quảng bá điều đó người dùng để dbo để họ ngừng làm phiền tôi. Thông thường, điều này được thực hiện khi các nhà phát triển vượt trội so với các DBA hoặc DBA cứng đầu. Điểm cuối cùng đó là điểm xấu của chúng tôi và chúng tôi cần phải cung cấp các truy vấn mà bạn cần tốt hơn.
  • Trên một lưu ý liên quan, một tập hợp các thủ tục được lưu trữ là một cách rất dễ dàng để kiểm kê chính xác những truy vấn nào có thể đang chạy trên hệ thống của tôi. Ngay sau khi một ứng dụng được phép bỏ qua các thủ tục và gửi các truy vấn đặc biệt của riêng nó, để tìm thấy chúng, tôi phải chạy một dấu vết bao trùm toàn bộ chu kỳ kinh doanh hoặc phân tích lại tất cả các mã ứng dụng (một lần nữa, đó là Tôi có thể không có quyền truy cập) để tìm bất cứ thứ gì trông giống như một truy vấn. Có thể xem danh sách các thủ tục được lưu trữ (và grep một nguồn duy nhất sys.sql_modules, để tham khảo các đối tượng cụ thể) làm cho cuộc sống của mọi người dễ dàng hơn nhiều.
  • Tôi có thể đi đến độ dài lớn hơn nhiều để ngăn chặn việc tiêm SQL; ngay cả khi tôi nhận đầu vào và thực thi nó bằng SQL động, tôi có thể kiểm soát rất nhiều điều được phép xảy ra. Tôi không có quyền kiểm soát đối với những gì nhà phát triển đang làm khi xây dựng các câu lệnh SQL nội tuyến.
  • Tôi có thể tối ưu hóa truy vấn (hoặc truy vấn) mà không cần truy cập vào mã nguồn ứng dụng, khả năng thay đổi, kiến ​​thức về ngôn ngữ ứng dụng để thực hiện một cách hiệu quả, cơ quan (không bao giờ bận tâm) để biên dịch lại và triển khai lại ứng dụng, vv Điều này đặc biệt có vấn đề nếu ứng dụng được phân phối.
  • Tôi có thể buộc các tùy chọn thiết lập nhất định trong quy trình được lưu trữ để tránh các truy vấn riêng lẻ phải chịu một số Chậm trong ứng dụng, nhanh trong SSMS không? các vấn đề. Có nghĩa là đối với hai ứng dụng khác nhau gọi một truy vấn ad hoc, một ứng dụng có thể có SET ANSI_WARNINGS ONvà ứng dụng kia có thể có SET ANSI_WARNINGS OFFvà mỗi ứng dụng sẽ có bản sao kế hoạch riêng. Kế hoạch họ nhận được phụ thuộc vào các tham số được sử dụng, số liệu thống kê, v.v. lần đầu tiên truy vấn được gọi trong mỗi trường hợp, điều này có thể dẫn đến các kế hoạch khác nhau và do đó hiệu suất rất khác nhau.
  • Tôi có thể kiểm soát những thứ như kiểu dữ liệu và cách sử dụng tham số, không giống như một số ORM nhất định - một số phiên bản trước đó của EF sẽ tham số hóa truy vấn dựa trên độ dài của tham số, vì vậy nếu tôi có tham số N'Smith 'và N' khác Johnson 'Tôi sẽ nhận được hai phiên bản khác nhau của kế hoạch. Họ đã sửa cái này. Họ đã sửa cái này nhưng cái gì khác vẫn bị hỏng?
  • Tôi có thể thực hiện những điều mà ORM và các khung và thư viện "hữu ích" khác chưa thể hỗ trợ.

Tất cả đã nói, câu hỏi này có khả năng khuấy động nhiều tranh luận tôn giáo hơn là tranh luận kỹ thuật. Nếu chúng ta thấy điều đó xảy ra, có lẽ chúng ta sẽ tắt nó.


2
Một lý do khác cho các thủ tục lưu trữ? Đối với các truy vấn dài, phức tạp, bạn phải đẩy truy vấn đến máy chủ mọi lúc, trừ khi đó là một sproc, thì về cơ bản bạn chỉ cần đẩy "exec sprocname" và một vài tham số. Điều này có thể tạo sự khác biệt trên mạng chậm (hoặc bận).
David Crowell

0

Trong khi tôi tôn trọng người đệ trình, tôi không đồng ý với câu trả lời được cung cấp và không vì "lý do tôn giáo". Nói cách khác, tôi tin rằng không có cơ sở nào mà Microsoft cung cấp làm giảm nhu cầu hướng dẫn sử dụng các thủ tục được lưu trữ.

Bất kỳ hướng dẫn nào được cung cấp cho nhà phát triển ưu tiên sử dụng các truy vấn SQL văn bản thô phải có nhiều cảnh báo, vì vậy tôi nghĩ rằng lời khuyên khôn ngoan nhất là khuyến khích rất nhiều việc sử dụng Quy trình được lưu trữ và không khuyến khích các nhóm nhà phát triển của bạn tham gia vào thực tiễn về việc nhúng các câu lệnh SQL trong mã hoặc gửi các yêu cầu SQL dựa trên văn bản thô, cũ, bên ngoài SQL SPROCs (các thủ tục được lưu trữ).

Tôi nghĩ rằng câu trả lời đơn giản cho câu hỏi tại sao sử dụng một XUÂN là do người nộp đã phỏng đoán: các XUÂN được phân tích cú pháp, tối ưu hóa và biên dịch. Như vậy, các gói truy vấn / thực thi của chúng được lưu trong bộ nhớ cache vì bạn đã lưu một biểu diễn tĩnh của truy vấn và thông thường, bạn sẽ chỉ thay đổi nó theo các tham số, điều này không đúng trong trường hợp các câu lệnh SQL được sao chép / dán có khả năng biến hình từ trang này sang trang khác và thành phần / tầng và thường được biến đổi theo phạm vi mà các bảng khác nhau, thậm chí tên cơ sở dữ liệu, có thể được chỉ định từ cuộc gọi đến cuộc gọi. Cho phép loại quảng cáo động nàyViệc gửi SQL, làm giảm đáng kể khả năng DB Engine sử dụng lại kế hoạch truy vấn cho các câu lệnh ad hoc của bạn, theo một số quy tắc rất nghiêm ngặt. Ở đây, tôi đang phân biệt giữa các truy vấn ad hoc động (theo tinh thần của câu hỏi được nêu ra) so với việc sử dụng Hệ thống sp_executesql hiệu quả của Hệ thống XUÂN.

Cụ thể hơn, có các thành phần sau:

  • Các gói truy vấn nối tiếp và song song không giữ ngữ cảnh người dùng và cho phép sử dụng lại bởi công cụ DB.
  • Bối cảnh thực thi cho phép người dùng mới sử dụng lại các gói truy vấn với các tham số dữ liệu khác nhau.
  • Bộ đệm thủ tục là những gì mà công cụ DB truy vấn để tạo ra hiệu quả mà chúng ta tìm kiếm.

Khi một câu lệnh SQL được phát ra từ một trang web, được gọi là "câu lệnh ad hoc", công cụ sẽ tìm một kế hoạch thực hiện hiện có để xử lý yêu cầu. Bởi vì đây là văn bản được gửi từ người dùng, nó sẽ được nhập, phân tích cú pháp, biên dịch và thực thi, nếu nó hợp lệ. Tại thời điểm này, nó sẽ nhận được một chi phí truy vấn bằng không. Chi phí truy vấn được sử dụng khi công cụ DB sử dụng thuật toán của nó để xác định kế hoạch thực hiện nào để đuổi khỏi bộ đệm.

Theo mặc định, các truy vấn đặc biệt nhận được giá trị truy vấn gốc bằng 0. Sau khi thực hiện chính xác văn bản truy vấn ad hoc chính xác, bởi một quá trình người dùng khác (hoặc cùng một quy trình), chi phí truy vấn hiện tại được đặt lại thành chi phí biên dịch ban đầu. Vì chi phí biên dịch truy vấn ad hoc của chúng tôi bằng không, nên điều này không tốt cho khả năng sử dụng lại. Rõ ràng, số 0 là số nguyên có giá trị thấp nhất, nhưng tại sao nó lại bị đuổi?

Khi áp lực bộ nhớ phát sinh và nếu bạn có một trang web thường được sử dụng, công cụ DB sẽ sử dụng thuật toán dọn dẹp để xác định cách nó có thể lấy lại bộ nhớ mà bộ đệm thủ tục đang sử dụng. Nó sử dụng chi phí truy vấn hiện tại để quyết định kế hoạch nào để đuổi. Như bạn có thể đoán, các gói có chi phí bằng 0 là lần đầu tiên bị đuổi khỏi bộ đệm vì về cơ bản số 0 có nghĩa là "không có người dùng hiện tại hoặc tham chiếu đến gói này".

  • Lưu ý: Kế hoạch thực hiện ad hoc - Chi phí hiện tại được tăng theo từng quy trình của người dùng, bằng chi phí biên dịch ban đầu của kế hoạch. Tuy nhiên, không có chi phí tối đa của kế hoạch có thể nhiều hơn chi phí biên dịch ban đầu của nó ... trong trường hợp truy vấn ad hoc ... bằng không. Vì vậy, nó sẽ được "tăng" bởi giá trị đó ... bằng không - điều đó có nghĩa là nó sẽ vẫn là gói chi phí thấp nhất.

Do đó, nhiều khả năng kế hoạch như vậy sẽ bị trục xuất trước tiên khi áp lực bộ nhớ xuất hiện.

Vì vậy, nếu bạn có một máy chủ tích hợp nhiều bộ nhớ "vượt quá nhu cầu của bạn", bạn có thể không gặp phải vấn đề này thường xuyên như một máy chủ bận rộn chỉ có bộ nhớ "đủ" để xử lý khối lượng công việc của nó. (Xin lỗi, dung lượng bộ nhớ máy chủ và việc sử dụng có phần chủ quan / tương đối, mặc dù thuật toán thì không.)

Bây giờ, nếu tôi thực sự không chính xác về một hoặc nhiều điểm, tôi chắc chắn sẵn sàng để được sửa chữa.

Cuối cùng, tác giả đã viết:

"Bây giờ chúng tôi đã tối ưu hóa mức câu lệnh, do đó, một truy vấn được tham số hóa chính xác đến từ một ứng dụng có thể tận dụng cùng một kế hoạch thực hiện như truy vấn đó được nhúng trong một thủ tục được lưu trữ."

Tôi tin rằng tác giả đang đề cập đến tùy chọn "tối ưu hóa cho khối lượng công việc ad hoc".

Nếu vậy, tùy chọn này cho phép một quy trình gồm hai bước để tránh ngay lập tức gửi gói truy vấn đầy đủ đến bộ đệm Thủ tục. Nó chỉ gửi một truy vấn nhỏ hơn ở đó. Nếu một cuộc gọi truy vấn chính xác được gửi trở lại máy chủ trong khi cuống truy vấn vẫn còn trong bộ đệm thủ tục, kế hoạch thực hiện truy vấn đầy đủ sẽ được lưu vào bộ đệm thủ tục, tại thời điểm đó. Điều này giúp tiết kiệm bộ nhớ, trong các sự cố áp suất bộ nhớ, có thể cho phép thuật toán trục xuất đuổi sơ khai của bạn ít thường xuyên hơn so với gói truy vấn lớn hơn được lưu trữ. Một lần nữa, điều này phụ thuộc vào bộ nhớ và sử dụng máy chủ của bạn.

Tuy nhiên, bạn phải bật tùy chọn này vì nó tắt theo mặc định.

Cuối cùng, tôi muốn nhấn mạnh rằng, thông thường, chính các nhà phát triển sẽ nhúng SQL vào các trang, thành phần và các vị trí khác, là vì họ muốn linh hoạt và gửi truy vấn SQL động đến công cụ cơ sở dữ liệu. Do đó, trong Trường hợp sử dụng trong thế giới thực, việc gửi cùng một văn bản, cuộc gọi qua cuộc gọi, dường như không xảy ra như bộ đệm / hiệu quả mà chúng tôi tìm kiếm, khi gửi truy vấn ad hoc đến SQL Server.

Để biết thêm thông tin, vui lòng xem:

https://technet.microsoft.com/en-us/l Library /
ms181055 (v = sql.105) .aspx http://sqlmag.com/database-performance-tuning/don-t-fear-dynamic-sql

Tốt nhất,
Henry


4
Tôi đã đọc qua một vài đoạn của bài viết của bạn, một cách cẩn thận, hai hoặc ba lần, và tôi vẫn không biết bạn đang cố gắng truyền đạt ý nghĩ gì. Trong một số trường hợp, bạn xuất hiện ở cuối câu để nói hoàn toàn ngược lại với những gì câu bắt đầu cố gắng nói. Bạn thực sự cần phải hiệu đính và chỉnh sửa trình này một cách cẩn thận.
Pieter Geerkens

Cảm ơn bạn đã phản hồi. Nếu đây là trường hợp, có thể là tôi nên rút ngắn câu của mình để làm cho điểm rõ ràng hơn. Bạn có thể vui lòng cung cấp một ví dụ về nơi tôi xuất hiện để nói ngược lại với suy nghĩ ban đầu không? Nhiều đánh giá cao.
Henry

Không, tôi không có nghĩa là Tối ưu hóa cho khối lượng công việc Ad Hoc, tôi có nghĩa là tối ưu hóa mức tuyên bố. Ví dụ, trong SQL Server 2000, một quy trình được lưu trữ sẽ được biên dịch toàn bộ, do đó, không có cách nào để ứng dụng sử dụng lại một kế hoạch cho truy vấn ad hoc của chính nó xảy ra để khớp với một cái gì đó trong quy trình. Tôi sẽ nói rằng tôi đồng ý với Pieter - rất nhiều điều bạn nói rất khó để làm theo. Những điều như "Tôi tin rằng không có cơ sở nào mà Microsoft đã cung cấp làm giảm nhu cầu hướng dẫn sử dụng các thủ tục được lưu trữ." là phức tạp không cần thiết và đòi hỏi quá nhiều phân tích để hiểu. IMHO.
Aaron Bertrand

1
có vẻ như ác cảm của bạn với "ad hoc" sql dựa trên ý tưởng rằng sql bằng cách nào đó thay đổi giữa các lần thực thi ... điều này hoàn toàn sai khi tham số hóa.
b_levitt

0

TLDR: Không có sự khác biệt hiệu suất đáng kể giữa hai miễn là sql nội tuyến của bạn được tham số hóa.

Đây là những lý do tôi dần dần loại bỏ các thủ tục được lưu trữ:

  • Chúng tôi chạy môi trường ứng dụng 'beta' - môi trường song song với sản xuất chia sẻ cơ sở dữ liệu sản xuất. Bởi vì, mã db ở cấp ứng dụng và thay đổi cấu trúc db rất hiếm, chúng tôi có thể cho phép mọi người xác nhận chức năng mới ngoài QA và triển khai bên ngoài cửa sổ triển khai sản xuất nhưng vẫn cung cấp chức năng sản xuất và sửa lỗi không quan trọng. Điều này sẽ không thể xảy ra nếu một nửa mã ứng dụng nằm trong DB.

  • Chúng tôi thực hành devops ở cấp cơ sở dữ liệu (bạch tuộc + dacpacs). Tuy nhiên, trong khi lớp kinh doanh trở lên về cơ bản có thể bị thanh trừng và thay thế và phục hồi hoàn toàn ngược lại, điều đó không đúng với những thay đổi gia tăng và có khả năng phá hủy phải đến cơ sở dữ liệu. Do đó, chúng tôi muốn giữ cho việc triển khai DB của chúng tôi nhẹ hơn và ít thường xuyên hơn.

  • Để tránh các bản sao chính xác của cùng một mã cho các tham số tùy chọn, chúng tôi thường sẽ sử dụng mẫu 'trong đó @var là null hoặc @ var = table.field'. Với một Proc được lưu trữ, bạn có thể có cùng một kế hoạch thực hiện, mặc dù có ý định khác nhau, và do đó gặp phải các vấn đề về hiệu suất hoặc loại bỏ các gói được lưu trong bộ nhớ cache với gợi ý 'biên dịch lại'. Tuy nhiên, với một đoạn mã đơn giản gắn thêm nhận xét "chữ ký" vào cuối sql, chúng ta có thể buộc các kế hoạch khác nhau dựa trên biến nào là null (không được hiểu là một kế hoạch khác nhau cho tất cả các kết hợp biến - chỉ null vs có giá trị).

  • Tôi có thể thực hiện các thay đổi đáng kể đối với kết quả chỉ bằng những thay đổi nhỏ khi đang bay đến sql. Ví dụ: tôi có thể có một tuyên bố kết thúc bằng hai CTE, "Raw" và "ReportReady". Không có gì nói rằng cả hai CTE phải được sử dụng Câu lệnh sql của tôi có thể là:

    ...

    chọn * từ {(định dạng)} "

Điều này cho phép tôi sử dụng cùng một phương pháp logic kinh doanh chính xác cho cả cuộc gọi api được sắp xếp hợp lý và báo cáo cần chi tiết hơn để đảm bảo rằng tôi không lặp lại logic phức tạp.

  • Khi bạn có quy tắc "chỉ procs", bạn sẽ có rất nhiều dư thừa trong phần lớn sql của bạn, kết thúc là CRUD - Bạn liên kết tất cả các tham số, bạn liệt kê tất cả các tham số đó trong chữ ký Proc, (và bây giờ bạn đang ở trong một tệp khác trong một dự án khác), bạn ánh xạ các tham số đơn giản đó vào các cột của chúng. Điều này tạo ra một kinh nghiệm phát triển khá rời rạc.

Có những lý do hợp lệ để sử dụng procs:

  • Bảo mật - Bạn đã có một lớp khác ở đây rằng ứng dụng phải hoạt động. Nếu tài khoản dịch vụ ứng dụng không được phép chạm vào các bảng, nhưng chỉ có quyền 'thực thi' trên các procs, bạn đã có thêm một số bảo vệ. Điều này không làm cho nó được đưa ra vì nó có chi phí, nhưng đó là một khả năng.

  • Tái sử dụng - Mặc dù tôi sẽ nói rằng việc tái sử dụng phần lớn sẽ xảy ra ở tầng doanh nghiệp để đảm bảo bạn không bỏ qua các quy tắc kinh doanh không liên quan đến db, nhưng chúng tôi vẫn có loại chức năng và chức năng tiện ích "được sử dụng ở mọi nơi" cấp độ thấp.

Có một số đối số không thực sự hỗ trợ procs hoặc dễ dàng giảm nhẹ IMO:

  • Tái sử dụng - Tôi đã đề cập ở trên là "cộng", nhưng cũng muốn đề cập ở đây rằng việc tái sử dụng phần lớn sẽ xảy ra ở tầng kinh doanh. Một Proc để chèn một bản ghi không nên được coi là "có thể sử dụng lại" khi lớp nghiệp vụ cũng có thể đang kiểm tra các dịch vụ không phải là db khác.

  • Sự phình to của gói bộ nhớ cache - cách duy nhất đây sẽ là một vấn đề là nếu bạn đang nối các giá trị thay vì tham số hóa. Thực tế là bạn hiếm khi nhận được nhiều hơn một kế hoạch cho mỗi Proc thực sự thường làm bạn tổn thương khi bạn có một 'hoặc' trong một truy vấn

  • Kích thước câu lệnh - một kb thêm của các câu lệnh sql trên tên Proc thường sẽ không đáng kể so với dữ liệu quay trở lại. Nếu nó ổn đối với các Thực thể, thì nó cũng ổn đối với tôi.

  • Xem truy vấn chính xác - Làm cho các truy vấn dễ tìm thấy trong mã cũng đơn giản như thêm vị trí gọi dưới dạng nhận xét vào mã. Tạo mã có thể sao chép từ mã c # sang ssms dễ dàng như một số cách sử dụng nội suy và nhận xét sáng tạo:

        //Usage /*{SSMSOnly_}*/Pure Sql To run in SSMS/*{_SSMSOnly}*/
        const string SSMSOnly_ = "*//*<SSMSOnly>/*";
        const string _SSMSOnly = "*/</SSMSOnly>";
        //Usage /*{NetOnly_}{InterpolationVariable}{_NetOnly}*/
        const string NetOnly_ = "*/";
        const string _NetOnly = "/*";
  • Sql tiêm - Tham số hóa các truy vấn của bạn. Làm xong. Điều này thực sự có thể được hoàn tác nếu thay vào đó là sử dụng sql động.

  • Bỏ qua việc triển khai - Chúng tôi cũng thực hành các tín đồ ở cấp cơ sở dữ liệu, vì vậy đây không phải là một tùy chọn cho chúng tôi.

  • "Chậm trong ứng dụng, nhanh trong SSMS" - Đây là vấn đề bộ nhớ đệm kế hoạch ảnh hưởng đến cả hai bên. Các tùy chọn thiết lập chỉ khiến cho một kế hoạch mới được biên dịch xuất hiện để khắc phục sự cố cho các biến THE ONE SET OFF. Điều này chỉ trả lời tại sao bạn thấy các kết quả khác nhau - bản thân các tùy chọn thiết lập KHÔNG khắc phục vấn đề đánh hơi thông số.

  • Kế hoạch thực hiện sql nội tuyến không được lưu trữ - Đơn giản là sai. Một câu lệnh được tham số hóa, giống như tên Proc được băm nhanh chóng và sau đó một kế hoạch được tìm kiếm bởi hàm băm đó. Nó giống nhau 100%.

  • Để rõ ràng, tôi đang nói về sql nội tuyến thô không được tạo mã từ ORM - chúng tôi chỉ sử dụng Dapper là một ORM vi mô tốt nhất.

https://weblogs.asp.net/fbouma/38178

https://stackoverflow.com/a/15277/852208

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.