Yêu cầu phổ biến trong ETL và các tình huống báo cáo khác nhau là tải một cách lặng lẽ bảng dàn SQL Server ở chế độ nền, do đó người dùng truy vấn dữ liệu không bị ảnh hưởng bởi việc ghi và ngược lại. Bí quyết là cách thức và thời điểm bạn hướng người dùng đến phiên bản mới, được làm mới của dữ liệu.
Ví dụ đơn giản về bảng phân giai đoạn:Tương tự thị trường nông dân
Vậy, bảng dàn trong SQL là gì? Có thể dễ hiểu hơn một bảng phân giai đoạn bằng cách sử dụng một ví dụ trong thế giới thực:Giả sử bạn có một bàn đầy rau mà bạn đang bán tại chợ nông sản địa phương. Khi rau của bạn bán và bạn có thêm hàng tồn kho mới:
- Khi bạn mang theo một đống rau mới, bạn sẽ mất 20 phút để dọn sạch bàn và thay thế kho còn lại bằng sản phẩm mới hơn.
- Bạn không muốn khách hàng ngồi đó và đợi 20 phút cho việc chuyển đổi diễn ra, vì hầu hết sẽ lấy rau của họ ở nơi khác.
Bây giờ, điều gì sẽ xảy ra nếu bạn có một bàn trống thứ hai, nơi bạn tải các loại rau mới và trong khi bạn đang làm việc đó, khách hàng vẫn có thể mua các loại rau cũ hơn từ bàn đầu tiên? (Hãy giả vờ rằng đó không phải là vì những loại rau cũ bị hỏng hoặc kém hấp dẫn hơn.)
Làm mới bảng trong SQL Server
Có một số phương pháp để tải lại toàn bộ bảng trong khi chúng đang được truy vấn; hai thập kỷ trước, tôi đã tận dụng lợi thế của sp_rename
- Tôi sẽ chơi trò chơi shell với một bản sao bóng trống của bảng, vui vẻ tải lại bản sao bóng mờ và sau đó chỉ thực hiện đổi tên bên trong một giao dịch.
Trong SQL Server 2005, tôi bắt đầu sử dụng lược đồ để giữ các bản sao bóng tối của các bảng mà tôi chỉ cần chuyển xung quanh bằng cách sử dụng cùng một kỹ thuật trò chơi shell mà tôi đã viết trong hai bài đăng sau:
- Trick Shots:Schema Switch-a-Roo
- Schema Switch-a-Roo, Phần 2
Ưu điểm duy nhất của việc chuyển các đối tượng giữa các lược đồ thay vì đổi tên chúng là không có thông báo cảnh báo nào về việc đổi tên đối tượng - điều này thậm chí không phải là vấn đề, ngoại trừ các thông báo cảnh báo lấp đầy nhật ký lịch sử tác nhân nhanh hơn nhiều.
Cả hai cách tiếp cận vẫn yêu cầu khóa sửa đổi lược đồ (Sch-M), vì vậy chúng phải đợi bất kỳ giao dịch hiện có nào giải phóng khóa của riêng chúng. Khi họ có được khóa Sch-M, họ sẽ chặn mọi truy vấn tiếp theo yêu cầu khóa ổn định của lược đồ (Sch-S)… đó là gần như mọi truy vấn. Nó có thể nhanh chóng trở thành cơn ác mộng của chuỗi chặn, vì bất kỳ truy vấn mới nào cần Sch-S đều phải xếp hàng sau Sch-M. (Và không, bạn không thể giải quyết vấn đề này bằng cách sử dụng RCSI hoặc NOLOCK
ở mọi nơi, vì ngay cả những truy vấn đó vẫn yêu cầu Sch-S. Bạn không thể mua Sch-S với Sch-M tại chỗ, vì chúng không tương thích với nhau — Michael J. Swart nói về điều đó ở đây.)
Kendra Little đã thực sự mở mang tầm mắt của tôi về những nguy hiểm với việc chuyển giản đồ trong bài đăng của cô ấy, “Dữ liệu theo giai đoạn:Khóa nguy hiểm với CHUYỂN SCHEMA ALTER”. Ở đó, cô ấy chỉ ra lý do tại sao chuyển lược đồ có thể tệ hơn đổi tên. Sau đó, cô ấy đã trình bày chi tiết một cách thứ ba và ít tác động hơn nhiều để hoán đổi các bảng, mà bây giờ tôi chỉ sử dụng:chuyển đổi phân vùng. Phương pháp này cho phép chuyển đổi chờ ở mức độ ưu tiên thấp hơn, thậm chí không phải là một tùy chọn với các kỹ thuật đổi tên hoặc chuyển lược đồ. Joe Sack đã đi vào chi tiết về tính năng nâng cao này được thêm lại trong SQL Server 2014:“Khám phá các tùy chọn chờ khóa ưu tiên thấp trong SQL Server 2014 CTP1.”
Ví dụ về chuyển đổi phân vùng máy chủ SQL
Hãy xem một ví dụ cơ bản, sau đây là ý chính của Kendra. Đầu tiên, chúng tôi sẽ tạo hai cơ sở dữ liệu mới:
TẠO CƠ SỞ DỮ LIỆU NewWay; TẠO CƠ SỞ DỮ LIỆU OldWay; ĐI
Trong cơ sở dữ liệu mới, chúng tôi sẽ tạo một bảng để chứa hàng tồn kho rau của chúng tôi và hai bản sao của bảng cho trò chơi shell của chúng tôi:
SỬ DỤNG NewWay; ĐI TẠO BẢNG dbo.Vegetables_NewWay (VegetableID int, Name sysname, WhenPicked datetime, BackStory nvarchar (max)); GO - chúng ta cần tạo thêm hai bản sao của bảng. TẠO BẢNG dbo.Vegetables_NewWay_prev (VegetableID int, Name sysname, WhenPicked datetime, BackStory nvarchar (max)); ĐI TẠO BẢNG dbo.Vegetables_NewWay_hold (VegetableID int, Name sysname, WhenPicked datetime, BackStory nvarchar (max)); ĐI
Chúng tôi tạo một thủ tục tải bản sao theo giai đoạn của bảng, sau đó sử dụng một giao dịch để chuyển bản sao hiện tại ra.
TẠO THỦ TỤC dbo.DoTheVeggieSwap_NewWayASBEGIN ĐẶT SỐ TÀI KHOẢN BẬT; BẢNG TRUNCATE dbo.Vegetables_NewWay_prev; CHÈN dbo.Vegetables_NewWay_prev CHỌN HÀNG ĐẦU (1000000) s.session_id, o.name, s.last_successful_logon, LEFT (m.definition, 500) TỪ sys.dm_exec_sessions AS s CROSS JOIN model.sys.all_objects AS o INNER JOIN model.sys. all_sql_modules AS m ON o. [object_id] =m. [object_id]; - cần lấy khóa Sch-M ở đây:BẮT ĐẦU GIAO DỊCH; ALTER TABLE dbo.Vegetables_NewWay CHUYỂN ĐỔI ĐẾN dbo.Vegetables_NewWay_hold WITH (WAIT_AT_LOW_PRIORITY (MAX_DURATION =1 MINUTES, ABORT_AFTER_WAIT =BLOCKERS)); ALTER TABLE dbo.Vegetables_NewWay_prev CHUYỂN ĐỔI THÀNH dbo.Vegetables_NewWay; CAM KẾT GIAO DỊCH; - và bây giờ người dùng sẽ truy vấn dữ liệu mới trong dbo - có thể chuyển bản sao cũ trở lại và cắt ngắn nó - mà không can thiệp vào các truy vấn khác ALTER TABLE dbo.Vegetables_NewWay_hold CHUYỂN ĐẾN dbo.Vegetables_NewWay_prev; BẢNG TRUNCATE dbo.Vegetables_NewWay_prev; ENDGO
Vẻ đẹp của WAIT_AT_LOW_PRIORITY
là bạn có thể hoàn toàn kiểm soát hành vi với ABORT_AFTER_WAIT
tùy chọn:
ABORT_AFTER_WAIT cài đặt | Mô tả / triệu chứng |
---|---|
TỰ | Điều này có nghĩa là nút chuyển sẽ từ bỏ sau n phút. Đối với phiên cố gắng thực hiện chuyển đổi, điều này sẽ hiển thị dưới dạng thông báo lỗi: Đã vượt quá khoảng thời gian chờ yêu cầu khóa. |
CHẶN CHẶN | Điều này cho biết công tắc sẽ đợi tối đa n vài phút, sau đó tự buộc mình lên hàng đầu bằng cách giết tất cả những kẻ chặn trước nó . Các phiên đang cố gắng tương tác với bảng bị tác động bởi thao tác chuyển đổi sẽ thấy một số thông báo lỗi kết hợp sau: Phiên của bạn đã bị ngắt kết nối do thao tác DDL có mức độ ưu tiên cao.Không thể tiếp tục thực thi vì phiên đang ở trạng thái kết thúc. Đã xảy ra lỗi nghiêm trọng trên lệnh hiện tại. Kết quả, nếu có, nên được loại bỏ. |
KHÔNG CÓ | Điều này cho biết nút chuyển sẽ vui vẻ đợi cho đến khi đến lượt, bất kể MAX_DURATION .
Đây là hành vi tương tự mà bạn sẽ gặp khi đổi tên, chuyển lược đồ hoặc chuyển đổi phân vùng mà không có |
BLOCKERS
tùy chọn không phải là cách thân thiện nhất để xử lý mọi việc, vì bạn đã nói rằng thông qua hoạt động phân đoạn / chuyển đổi này, người dùng có thể thấy dữ liệu đã lỗi thời một chút. Tôi có thể thích sử dụng SELF
và yêu cầu hoạt động thử lại trong trường hợp nó không thể nhận được các khóa cần thiết trong thời gian quy định. Tuy nhiên, tôi sẽ theo dõi tần suất nó bị lỗi, đặc biệt là những lỗi liên tiếp, vì bạn muốn đảm bảo rằng dữ liệu không bao giờ quá cũ.
So với cách chuyển đổi cũ giữa các lược đồ
Đây là cách tôi sẽ xử lý việc chuyển đổi trước đây:
« max)); ĐI TẠO TABLE trước.Vegetables_OldWay (VegetableID int, Name sysname, WhenPicked datetime, BackStory nvarchar (max)); ĐI TẠO TIẾN TRÌNH dbo.DoTheVeggieSwap_OldWayASBEGIN ĐẶT TÀI KHOẢN BẬT; TRUNCATE TABLE trước.Vegetables_OldWay; CHÈN TRƯỚC.Vegetables_OldWay CHỌN ĐẦU (1000000) s.session_id, o.name, s.last_successful_logon, LEFT (m.definition, 500) TỪ sys.dm_exec_sessions AS s CROSS JOIN model.sys.all_objects AS o INNER JOIN model.sys. all_sql_modules AS m ON o. [object_id] =m. [object_id]; - cần lấy khóa Sch-M ở đây:BẮT ĐẦU GIAO DỊCH; ALTER SCHEMA giữ TRANSFER dbo.Vegetables_OldWay; ALTER SCHEMA dbo TRANSFER trước.Vegetables_OldWay; CAM KẾT GIAO DỊCH; - và bây giờ người dùng sẽ truy vấn dữ liệu mới trong dbo - có thể chuyển bản sao cũ trở lại và cắt ngắn nó mà không - can thiệp vào các truy vấn khác:ALTER SCHEMA TRANSFER TRANSFER hold.Vegetables_OldWay; TRUNCATE TABLE trước.Vegetables_OldWay; ENDGOTôi đã chạy các bài kiểm tra đồng thời bằng cách sử dụng hai cửa sổ SQLQueryS Stress của Erik Ejlskov Jensen:một cửa sổ để lặp lại lệnh gọi thủ tục mỗi phút và cửa sổ kia để chạy 16 luồng như thế này, hàng nghìn lần:
BẮT ĐẦU GIAO DỊCH; CẬP NHẬT ĐẦU (1) dbo.
Thời lượng và Tỷ lệ Lỗi | Chuyển lược đồ | ABORT_AFTER_WAIT: TỰ | ABORT_AFTER_WAIT: BLOCKERS |
---|---|---|---|
Thời lượng trung bình - Chuyển / Chuyển đổi | 96,4 giây | 68,4 giây | 20,8 giây |
Thời lượng Trung bình - DML | 18,7 giây | 2,7 giây | 2,9 giây |
Ngoại lệ - Chuyển / Chuyển đổi | 0 | 0,5 / phút | 0 |
Ngoại lệ - DML | 0 | 0 | 25,5 / phút |
Lưu ý rằng thời lượng và số lượng ngoại lệ sẽ phụ thuộc nhiều vào thông số kỹ thuật máy chủ của bạn và những gì khác đang diễn ra trong môi trường của bạn. Cũng lưu ý rằng, mặc dù không có ngoại lệ đối với các bài kiểm tra chuyển lược đồ khi sử dụng SQLQueryS Stress, nhưng bạn có thể gặp phải một số thời gian chờ nghiêm ngặt hơn tùy thuộc vào ứng dụng đang sử dụng. Và trung bình nó chậm hơn rất nhiều, bởi vì việc chặn chồng chất mạnh hơn nhiều. Không ai muốn ngoại lệ, nhưng khi có sự đánh đổi như thế này, bạn có thể thích một vài ngoại lệ ở đây và ở đó (tùy thuộc vào tần suất của hoạt động làm mới) hơn là mọi người luôn chờ đợi lâu hơn.
Chuyển phân vùng so với Đổi tên / Chuyển giản đồ để làm mới bảng máy chủ SQL
Chuyển đổi phân vùng cho phép bạn chọn phần nào trong quy trình của bạn chịu chi phí tương tự. Bạn có thể ưu tiên cho quá trình chuyển đổi để dữ liệu được làm mới đáng tin cậy hơn, nhưng điều này có nghĩa là một số truy vấn của bạn sẽ không thành công. Ngược lại, bạn có thể ưu tiên các truy vấn, với chi phí là quá trình làm mới chậm hơn (và thỉnh thoảng xảy ra lỗi ở đó). Lực đẩy chính là chuyển đổi phân vùng SQL Server là một phương pháp vượt trội để làm mới bảng SQL Server so với các kỹ thuật chuyển đổi tên / lược đồ trước đó trên hầu hết các điểm và bạn có thể sử dụng logic thử lại mạnh mẽ hơn hoặc thử nghiệm với dung sai thời lượng để đạt được điểm tốt cho khối lượng công việc của bạn.