125

Tôi có thể hiểu rằng muốn tránh phải sử dụng một con trỏ do chi phí quá cao và sự bất tiện, nhưng có vẻ như có một số ám ảnh nghiêm trọng về con trỏ đang diễn ra trong đó mọi người sẽ cố gắng hết sức để tránh phải sử dụng một con trỏ.

Ví dụ: một câu hỏi hỏi cách thực hiện một cái gì đó rõ ràng tầm thường với một con trỏ và câu trả lời được chấp nhận được đề xuất bằng cách sử dụng truy vấn đệ quy biểu thức bảng chung (CTE) với hàm tùy chỉnh đệ quy, mặc dù điều này giới hạn số lượng hàng có thể được xử lý là 32 (do giới hạn gọi hàm đệ quy trong máy chủ sql). Đây là một giải pháp khủng khiếp cho tuổi thọ hệ thống, chưa kể đến một nỗ lực to lớn chỉ để tránh sử dụng một con trỏ đơn giản.

Lý do cho mức độ thù hận điên rồ này là gì? Có một số 'cơ quan có thẩm quyền' đã ban hành một fatwa chống lại con trỏ? Có một số điều xấu xa không thể nói được ẩn giấu trong trái tim của những kẻ nguyền rủa làm hỏng đạo đức của trẻ em hay cái gì đó?

Wiki câu hỏi, quan tâm đến câu trả lời hơn các đại diện.

Thông tin liên quan:

Máy chủ chuyển tiếp nhanh SQL Server

EDIT: hãy để tôi chính xác hơn: Tôi hiểu rằng không nên sử dụng các con trỏ thay vì các hoạt động quan hệ thông thường ; đó là một người không có trí tuệ Điều tôi không hiểu là mọi người sẽ cố gắng tránh những con trỏ như họ có coot hay gì đó, ngay cả khi con trỏ là một giải pháp đơn giản và hiệu quả hơn. Đó là sự thù hận phi lý gây trở ngại cho tôi, không phải là hiệu quả kỹ thuật rõ ràng.

|
  • 1

    Tôi nghĩ rằng Chỉnh sửa của bạn nói lên tất cả ... Trong hầu hết tất cả các tình huống (mà tôi đã gặp) có một cách để thay thế một con trỏ bằng một tình huống dựa trên thiết lập hiệu suất tốt hơn. Bạn nói không có trí tuệ, nhưng bạn hiểu khác biệt.

    – Trần Phương Thảo 18:28:24 13/11/2008
  • 6

    Tôi thích các thẻ về câu hỏi này!

    – Lê Thế Tùng 15:09:52 14/11/2008
  • 2

    Phần về giới hạn CTE đệ quy 32là vô nghĩa. Có lẽ bạn đang nghĩ đến trigger đệ quy và tối đa @@NESTLEVELcủa 32. Nó có thể được đặt trong truy vấn OPTION (MAXRECURSION N)với mặc định 1000có nghĩa là không giới hạn.

    – Trần Hoàng Lâm 13:33:02 02/11/2012
  • @MartinSmith: giới hạn mặc định là 100 và tối đa là 32K sql-server-helper.com/error-messages/msg-310.aspx

    – Ngô Nhất Thương 23:00:03 11/01/2016
  • Không, nó vẫn giống hệt như khi tôi đưa ra nhận xét của mình và trong tất cả các phiên bản SQL Server hỗ trợ CTE đệ quy. Như liên kết của bạn nói "Khi 0 được chỉ định, không có giới hạn nào được áp dụng."

    – Hoàng Ðức Trung 23:37:54 11/01/2016
73

"Chi phí" với các con trỏ chỉ là một phần của API. Các con trỏ là cách các phần của RDBMS hoạt động dưới mui xe. Thường CREATE TABLEINSERTcó các SELECTcâu lệnh, và việc thực hiện là triển khai con trỏ bên trong rõ ràng.

Sử dụng "toán tử dựa trên tập hợp" cấp cao hơn sẽ kết hợp các kết quả con trỏ thành một tập kết quả duy nhất, nghĩa là ít qua lại API hơn.

Con trỏ có trước các ngôn ngữ hiện đại cung cấp các bộ sưu tập hạng nhất. Old C, COBOL, Fortran, v.v., đã phải xử lý từng hàng một vì không có khái niệm "bộ sưu tập" nào có thể được sử dụng rộng rãi. Java, C #, Python, v.v., có cấu trúc danh sách hạng nhất để chứa các tập kết quả.

Vấn đề chậm

Trong một số vòng tròn, các phép nối quan hệ là một bí ẩn và mọi người sẽ viết các con trỏ lồng nhau thay vì nối đơn giản. Tôi đã thấy các hoạt động vòng lặp lồng nhau thực sự hoành tráng được viết ra rất nhiều và nhiều con trỏ. Đánh bại tối ưu hóa RDBMS. Và chạy rất chậm.

SQL đơn giản viết lại để thay thế các vòng lặp con trỏ lồng nhau bằng các phép nối và một vòng lặp con trỏ đơn, phẳng có thể làm cho các chương trình chạy trong 100 lần. [Họ nghĩ tôi là thần tối ưu. Tất cả tôi đã làm là thay thế các vòng lặp lồng nhau bằng các phép nối. Vẫn sử dụng con trỏ.]

Sự nhầm lẫn này thường dẫn đến một bản cáo trạng của con trỏ. Tuy nhiên, đó không phải là con trỏ, đó là sự lạm dụng của con trỏ là vấn đề.

Vấn đề kích thước

Đối với các tập kết quả thực sự hoành tráng (nghĩa là bỏ bảng vào một tệp), con trỏ là rất cần thiết. Các hoạt động dựa trên tập hợp không thể cụ thể hóa các tập kết quả thực sự lớn thành một bộ sưu tập duy nhất trong bộ nhớ.

Lựa chọn thay thế

Tôi cố gắng sử dụng một lớp ORM càng nhiều càng tốt. Nhưng điều đó có hai mục đích. Đầu tiên, các con trỏ được quản lý bởi thành phần ORM. Thứ hai, SQL được tách ra khỏi ứng dụng thành một tệp cấu hình. Không phải là những con trỏ xấu. Đó là mã hóa tất cả những gì mở, đóng và tìm nạp không phải là lập trình giá trị gia tăng.

|
  • 1

    "Các con trỏ là cách RDBMS hoạt động dưới mui xe." Nếu bạn có nghĩa cụ thể là SQL Server, OK, tốt, tôi không biết gì về điều đó. Nhưng tôi đã làm việc trên các phần bên trong của nhiều RDBMS (và ORDBMS) (dưới Stonebraker) và không ai trong số họ làm điều đó. Ví dụ: Ingres sử dụng số tiền cho "tập kết quả" của bộ dữ liệu trong nội bộ.

    – Hồ Ánh Linh 16:49:23 28/12/2008
  • 1

    @Richard T: Tôi đang xử lý thông tin cũ về nguồn RDBMS; Tôi sẽ sửa đổi tuyên bố.

    – Hồ Công Phụng 18:42:13 28/12/2008
  • 1

    "Tôi đã thấy các hoạt động vòng lặp lồng nhau thực sự hoành tráng được viết ra rất nhiều và rất nhiều con trỏ." Tôi tiếp tục nhìn thấy chúng quá. Thật khó có thể tin.

    – Nguyễn Ngọc 01:26:42 30/12/2008
41

Con trỏ làm cho mọi người áp dụng quá mức một tư duy thủ tục vào một môi trường dựa trên tập hợp.

Và họ đang CHẬM !!!

Từ SQLTeam :

Xin lưu ý rằng các con trỏ là cách TUYỆT VỜI nhất để truy cập dữ liệu trong SQL Server. Chỉ nên được sử dụng khi bạn thực sự cần truy cập một hàng tại một thời điểm. Lý do duy nhất tôi có thể nghĩ đến đó là gọi một thủ tục được lưu trữ trên mỗi hàng. Trong bài viết Hiệu suất con trỏ, tôi phát hiện ra rằng các con trỏ chậm hơn ba mươi lần so với các lựa chọn thay thế dựa trên thiết lập .

|
  • 1

    Bài báo đó đã 7 tuổi, bạn có nghĩ rằng có lẽ mọi thứ đã thay đổi trong lúc này không?

    – Hồ Ánh Linh 16:46:56 13/11/2008
  • 1

    Tôi cũng nghĩ rằng con trỏ rất chậm và nói chung là nên tránh. Tuy nhiên, nếu OP đang đề cập đến câu hỏi mà tôi nghĩ là anh ta, thì một con trỏ là giải pháp chính xác ở đó (phát trực tiếp bản ghi một lần do hạn chế về bộ nhớ).

    – Hồ Công Phụng 16:49:03 13/11/2008
  • 1

    bài viết cập nhật không sửa các phép đo tốc độ tương đối, nhưng nó cung cấp một số tối ưu hóa và lựa chọn thay thế tốt. Lưu ý rằng bài viết gốc nói rằng các con trỏ nhanh hơn 50 lần so với các vòng lặp, điều này rất thú vị

    – Nguyễn Ngọc 17:02:07 13/11/2008
  • 1

    @BoltBait: Cá nhân tôi nghĩ rằng nếu bạn đưa ra những khẳng định về chăn như thế thì bạn thực sự không thể 45 tuổi :-P

    – Đặng Hữu Tuấn 03:30:07 14/11/2008
  • 1

    @BoltBait: Các em xuống bãi cỏ của tôi!

    – Phan Phương Giang 23:36:15 19/11/2008
19

Có một câu trả lời ở trên có nội dung "con trỏ là cách TUYỆT VỜI nhất để truy cập dữ liệu bên trong SQL Server ... con trỏ chậm hơn ba mươi lần so với các lựa chọn thay thế dựa trên thiết lập."

Tuyên bố này có thể đúng trong nhiều trường hợp, nhưng như một tuyên bố về chăn thì nó có vấn đề. Ví dụ: tôi đã sử dụng tốt các con trỏ trong các tình huống tôi muốn thực hiện cập nhật hoặc xóa hoạt động ảnh hưởng đến nhiều hàng của một bảng lớn đang nhận được số lần đọc sản xuất liên tục. Chạy một thủ tục được lưu trữ mà các cập nhật này mỗi lần cập nhật nhanh hơn các hoạt động dựa trên tập hợp, bởi vì hoạt động dựa trên tập hợp mâu thuẫn với hoạt động đọc và kết thúc gây ra sự cố khóa khủng khiếp (và có thể giết chết hoàn toàn hệ thống sản xuất, trong trường hợp cực đoan).

Trong trường hợp không có hoạt động cơ sở dữ liệu khác, các hoạt động dựa trên tập hợp sẽ nhanh hơn. Trong các hệ thống sản xuất, nó phụ thuộc.

|
  • 1

    @ [Joel Coehoorn]: Tôi chưa bao giờ hiểu câu nói đó.

    – Hồ Ân Lai 17:04:37 13/11/2008
  • 1

    @ [Steven A. Lowe] cụm từ.org.uk/meanings/ exception- that-proves-the-rule.html hiểu ngoại lệ là "những gì bị bỏ rơi" và lưu ý rằng quy tắc ở đây là một cái gì đó như "trong hầu hết các con trỏ tình huống là xấu".

    – Tạ Bảo Uyên 17:18:30 13/11/2008
  • 1

    @ [Steven A. Lowe] Về cơ bản, nó nói rằng nếu bạn "phá vỡ một quy tắc" bằng một chữ con, thì phải có một quy tắc chung để phá vỡ, tồn tại một quy tắc tồn tại. ví dụ: Từ Liên kết: ("Nếu chúng tôi có một tuyên bố như 'mục nhập miễn phí vào Chủ nhật', chúng tôi có thể giả định một cách hợp lý rằng, như một quy tắc chung, mục nhập được tính phí.")

    – Đỗ Trường Phúc 17:35:40 13/11/2008
  • 1

    @Fry: ok điều đó có ý nghĩa - vậy làm thế nào để áp dụng ở đây?

    – Đỗ Hoàng Phát 17:53:55 13/11/2008
  • 1

    Tôi nghĩ ngần ngại nói rằng khi có vấn đề về khóa / hạn chế bộ nhớ, hãy sử dụng con trỏ. Điều này ngụ ý rằng bạn không nên sử dụng con trỏ khác.

    – Huỳnh Quang Bảo 04:00:54 27/02/2010
9

Trình tối ưu hóa thường không thể sử dụng đại số quan hệ để biến đổi vấn đề khi sử dụng phương pháp con trỏ. Thông thường, một con trỏ là một cách tuyệt vời để giải quyết vấn đề, nhưng SQL là ngôn ngữ khai báo và có rất nhiều thông tin trong cơ sở dữ liệu, từ các ràng buộc, đến thống kê và chỉ mục có nghĩa là trình tối ưu hóa có rất nhiều tùy chọn để giải quyết vấn đề, trong khi một con trỏ khá rõ ràng chỉ đạo giải pháp.

|
9

Các con trỏ có xu hướng được sử dụng bởi các nhà phát triển SQL bắt đầu ở những nơi mà các hoạt động dựa trên tập hợp sẽ tốt hơn. Đặc biệt khi mọi người học SQL sau khi học một ngôn ngữ lập trình truyền thống, tâm lý "lặp đi lặp lại những hồ sơ này" có xu hướng khiến mọi người sử dụng con trỏ không phù hợp.

Hầu hết các sách SQL nghiêm túc bao gồm một chương liên quan đến việc sử dụng các con trỏ; những người được viết tốt cho thấy rõ rằng các con trỏ có vị trí của chúng nhưng không nên được sử dụng cho các hoạt động dựa trên tập hợp.

Rõ ràng có những tình huống mà con trỏ là lựa chọn chính xác, hoặc ít nhất là một lựa chọn chính xác.

|
8

Trong các con trỏ Oracle PL / SQL sẽ không dẫn đến khóa bảng và có thể sử dụng thu thập hàng loạt / tìm nạp hàng loạt.

Trong Oracle 10, con trỏ ẩn thường được sử dụng

  for x in (select ....) loop
    --do something 
  end loop;

tìm nạp ngầm 100 hàng cùng một lúc. Cũng có thể thu thập số lượng lớn / tìm nạp số lượng lớn.

Tuy nhiên, các con trỏ PL / SQL là một cái gì đó cuối cùng, hãy sử dụng chúng khi bạn không thể giải quyết vấn đề với SQL dựa trên tập hợp.

Một lý do khác là song song hóa, cơ sở dữ liệu sẽ dễ dàng song song hóa các câu lệnh dựa trên tập lớn hơn so với mã mệnh lệnh theo hàng. Đó là cùng một lý do tại sao lập trình chức năng ngày càng trở nên phổ biến (Haskell, F #, Lisp, C # LINQ, MapReduce ...), lập trình chức năng giúp việc song song hóa dễ dàng hơn. Số lượng CPU trên mỗi máy tính đang tăng lên nên việc song song hóa ngày càng trở thành một vấn đề.

|
6

Các câu trả lời ở trên chưa nhấn mạnh đủ tầm quan trọng của việc khóa. Tôi không phải là một fan hâm mộ lớn của các con trỏ bởi vì chúng thường dẫn đến khóa cấp bảng.

|
  • 1

    Vâng, cảm ơn! Không có tùy chọn để ngăn chặn nó (chỉ đọc, chỉ chuyển tiếp, v.v.), chắc chắn họ sẽ, cũng như mọi hoạt động (máy chủ sql) sẽ tiến hành chiếm vài hàng và sau đó là vài trang hàng.

    – Nguyễn Thuỳ Dương 01:14:46 29/12/2008
  • 1

    ?? Đó là một vấn đề với chiến lược khóa của bạn KHÔNG phải là con trỏ. Ngay cả một câu lệnh CHỌN sẽ thêm khóa đọc.

    – Dương Thiên Trang 16:48:12 13/03/2019
6

Nói chung, vì trên cơ sở dữ liệu quan hệ, hiệu năng của mã sử dụng con trỏ là một thứ tự có độ lớn kém hơn các hoạt động dựa trên tập hợp.

|
  • 1

    Bạn có một điểm chuẩn hoặc tài liệu tham khảo cho điều này? tôi đã không nhận thấy bất kỳ sự suy giảm hiệu suất mạnh mẽ như vậy ... nhưng có lẽ các bảng của tôi không có đủ hàng cho vấn đề đó (thường là một triệu hoặc ít hơn)?

    – Nguyễn Thuỳ Dương 16:43:36 13/11/2008
  • 1

    oh chờ đã, tôi hiểu ý của bạn - nhưng tôi sẽ không bao giờ ủng hộ việc sử dụng con trỏ trong các thao tác đã đặt, chỉ không đi đến cực đoan để tránh con trỏ

    – Dương Thiên Trang 17:08:01 13/11/2008
  • 1

    Tôi nhớ lần đầu tiên tôi làm SQL, chúng tôi phải nhập tệp dữ liệu 50 nghìn hàng ngày từ máy tính lớn vào cơ sở dữ liệu SQL Server ... Tôi đã sử dụng một con trỏ và phát hiện ra rằng quá trình nhập mất khoảng 26 giờ bằng cách sử dụng con trỏ .. Khi tôi thay đổi thành các hoạt động dựa trên thiết lập, quá trình này mất 20 phút.

    – Ngô Tấn Khang 17:09:10 13/11/2008
3

Đối với những gì đáng giá tôi đã đọc rằng "một" nơi con trỏ sẽ thực hiện đối tác dựa trên tập hợp của nó trong tổng số đang chạy. Trên một bảng nhỏ, tốc độ tổng hợp các hàng theo thứ tự theo các cột ủng hộ hoạt động dựa trên tập hợp nhưng khi bảng tăng kích thước hàng, con trỏ sẽ trở nên nhanh hơn vì đơn giản là nó có thể mang tổng giá trị đang chạy đến lần truyền tiếp theo của vòng lặp. Bây giờ , nơi bạn nên thực hiện tổng cộng là một đối số khác nhau ...

|
  • 1

    Nếu bạn có nghĩa là bằng cách "chạy tổng cộng" một loại tổng hợp nào đó (tối thiểu, tối đa, tổng), thì bất kỳ DBMS có thẩm quyền nào cũng sẽ đánh bại quần của một giải pháp dựa trên con trỏ, nếu chỉ vì chức năng được thực hiện trong động cơ và không có máy khách <-> trên máy chủ. Có lẽ SQL Server không đủ năng lực?

    – Nguyễn Thuỳ Dương 16:44:29 28/12/2008
  • 1

    @ [Richard T]: chúng tôi đang thảo luận về con trỏ phía máy chủ, như trong một thủ tục được lưu trữ, không phải là con trỏ phía máy khách; xin lỗi vì sự nhầm lẫn!

    – Dương Thiên Trang 01:15:32 29/12/2008
2

Ngoài các vấn đề về hiệu năng (không), tôi nghĩ rằng thất bại lớn nhất của các con trỏ là chúng rất khó để gỡ lỗi. Đặc biệt so với mã trong hầu hết các ứng dụng khách, nơi gỡ lỗi có xu hướng tương đối dễ dàng và các tính năng ngôn ngữ có xu hướng dễ dàng hơn nhiều. Trên thực tế, tôi cho rằng gần như mọi thứ người ta đang làm trong SQL bằng một con trỏ có thể sẽ xảy ra trong ứng dụng khách ngay từ đầu.

|
  • 1

    SQL là đau đớn để gỡ lỗi, ngay cả khi không có con trỏ. Các công cụ chuyển đổi MS SQL trong Visual Studio dường như không thích tôi (chúng treo rất nhiều hoặc hoàn toàn không có điểm dừng), vì vậy tôi thường rút gọn thành các câu lệnh IN ;-)

    – Lý Phước Lộc 03:43:24 10/06/2009
2

Tôi đồng ý với bài viết trên trang này:

http://weblogs.sqlteam.com/jeffs/archive/2008/06/05/sql-server-coder-removal.aspx

|
1

Bạn có thể đã kết luận câu hỏi của bạn sau đoạn thứ hai, thay vì gọi mọi người là "điên rồ" chỉ vì họ có quan điểm khác với bạn và cố gắng chế giễu các chuyên gia có thể có lý do rất chính đáng để cảm nhận theo cách họ làm.

Đối với câu hỏi của bạn, trong khi chắc chắn có những tình huống có thể gọi con trỏ, nhưng theo kinh nghiệm của tôi, các nhà phát triển quyết định rằng con trỏ "phải" được sử dụng FAR thường xuyên hơn thực tế. Theo tôi, khả năng ai đó mắc lỗi khi sử dụng quá nhiều con trỏ so với việc không sử dụng chúng khi họ nên cao hơn theo quan điểm của tôi.

|
  • 1

    xin vui lòng đọc kỹ hơn, Tom - cụm từ chính xác là "hận thù điên rồ"; "Ghét" là đối tượng của tính từ "điên", không phải "người". Tiếng Anh đôi khi có thể hơi khó khăn ;-)

    – Lý Phước Lộc 18:55:01 13/11/2008
1

Bạn có thể gửi ví dụ con trỏ hoặc liên kết đến câu hỏi? Có lẽ có một cách thậm chí còn tốt hơn so với CTE đệ quy.

Ngoài các bình luận khác, con trỏ khi sử dụng không đúng cách (thường là) gây ra khóa trang / hàng không cần thiết.

|

Câu trả lời của bạn (> 20 ký tự)

Bằng cách click "Đăng trả lời", bạn đồng ý với Điều khoản dịch vụ, Chính sách bảo mật and Chính sách cookie của chúng tôi.

Không tìm thấy câu trả lời bạn tìm kiếm? Duyệt qua các câu hỏi được gắn thẻ hoặc hỏi câu hỏi của bạn.