Database
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Database

Hiệu suất của sys.partitions

sys.partitions dường như là một ĐOÀN KẾT TẤT CẢ của hai tập kết quả (lưu trữ hàng và tập hợp cột) và hầu hết các truy vấn của tôi đều dẫn đến hai lần quét tập hợp hệ thống. Có bất kỳ bộ lọc nào mà tôi có thể đặt trên một truy vấn sys.partitions nếu tôi biết hàng tôi đang tìm kiếm là cửa hàng hàng không?

Câu hỏi này đã được đăng lên #sqlhelp bởi Jake Manske và tôi đã thu hút sự chú ý của Erik Darling.

Tôi không nhớ đã từng gặp sự cố hiệu suất với sys.partitions . Suy nghĩ ban đầu của tôi (được nhắc lại bởi Joey D'Antoni) là một bộ lọc trên data_compression cột nên tránh quét dư thừa và giảm khoảng một nửa thời gian chạy truy vấn. Tuy nhiên, vị từ này không bị đẩy xuống và lý do tại sao cần một chút giải nén.

Tại sao sys.partitions chậm?

Nếu bạn nhìn vào định nghĩa cho sys.partitions , về cơ bản đó là những gì Jake đã mô tả - một UNION ALL của tất cả các phân vùng kho hàng và kho hàng, với BA tham chiếu rõ ràng đến sys.sysrowsets (nguồn viết tắt tại đây):

 TẠO XEM sys.partitions NHƯ VỚI partition_columnstore (... cols ...) AS (SELECT ... cols ..., cmprlevel AS data_compression ... FROM sys.sysrowsets rs NGOÀI RA ÁP DỤNG OpenRowset (BẢNG ALUCOUNT, rs .rowsetid, 0, 0, 0) ct -------- *** ^^^^^^^^^^^^^^^ *** TRÁI THAM GIA sys.syspalvalues ​​cl ... Ở ĐÂU .. . sysconv (bit, rs.status &0x00010000) =1 - Chỉ xem xét các chỉ mục cơ sở columnstore), phân vùng_rowstore (... cols ...) AS (SELECT ... cols ..., cmprlevel AS data_compression ... FROM sys.sysrowsets rs -------- *** ^^^^^^^^^^^^^^^ *** TRÁI THAM GIA sys.syspalvalues ​​cl ... WHERE ... sysconv (bit, rs .status &0x00010000) =0 - Bỏ qua chỉ mục cơ sở columnstore và các hàng mồ côi.) CHỌN ... cột ... từ phân vùng_rowstore p NGOÀI RA ÁP DỤNG OpenRowset (BẢNG ALUCOUNT, p.partition_id, 0, 0, p.object_id) ct union tất cả SELECT ... cols ... FROM partition_columnstore as P1 LEFT JOIN (CHỌN ... cols ... FROM sys.sysrowsets rs OUTER APP LY OpenRowset (TABLE ALUCOUNT, rs.rowsetid, 0, 0, 0) ct ------- *** ^^^^^^^^^^^^^^ ***) ...  

Quan điểm này có vẻ được kết hợp với nhau, có thể là do lo ngại về khả năng tương thích ngược. Nó chắc chắn có thể được viết lại để hiệu quả hơn, đặc biệt là để chỉ tham chiếu đến sys.sysrowsetsTABLE ALUCOUNT đối tượng một lần. Nhưng bạn hoặc tôi không thể làm gì nhiều về điều đó ngay bây giờ.

Cột cmprlevel đến từ sys.sysrowsets (một tiền tố bí danh trên tham chiếu cột sẽ hữu ích). Bạn hy vọng rằng một vị từ chống lại một cột ở đó sẽ xảy ra một cách hợp lý trước bất kỳ OUTER APPLY nào và có thể ngăn chặn một trong các lần quét, nhưng đó không phải là điều xảy ra. Chạy truy vấn đơn giản sau:

 CHỌN * TỪ sys.partitions AS p INNER THAM GIA sys.objects AS o ON p.object_id =o.object_id WHERE o.is_ms_shipped =0; 

Mang lại kế hoạch sau khi có các chỉ mục cột trong cơ sở dữ liệu (bấm để phóng to):

Lập kế hoạch cho sys.partitions, với các chỉ mục columnstore hiện diện

Và kế hoạch sau đây khi không có (bấm vào để phóng to):

Lập kế hoạch cho sys.partitions, không có chỉ mục cột nào

Đây là cùng một kế hoạch ước tính, nhưng SentryOne Plan Explorer có thể đánh dấu khi một thao tác bị bỏ qua trong thời gian chạy. Điều này xảy ra cho lần quét thứ ba trong trường hợp thứ hai, nhưng tôi không biết rằng có bất kỳ cách nào để giảm số lần quét thời gian chạy đó hơn nữa; lần quét thứ hai xảy ra ngay cả khi truy vấn trả về không hàng.

Trong trường hợp của Jake, anh ấy có rất nhiều của các đối tượng, vì vậy việc thực hiện quét này thậm chí hai lần là đáng chú ý, gây đau đớn và một lần là quá nhiều. Và thành thật mà nói, tôi không biết liệu TABLE ALUCOUNT , một lệnh gọi lặp lại nội bộ và không có tài liệu, cũng phải quét một số đối tượng lớn hơn này nhiều lần.

Nhìn lại nguồn, tôi tự hỏi liệu có bất kỳ vị từ nào khác có thể được chuyển đến chế độ xem có thể ép buộc hình dạng kế hoạch hay không, nhưng tôi thực sự không nghĩ rằng có bất cứ điều gì có thể có tác động.

Chế độ xem khác có hoạt động không?

Tuy nhiên, chúng tôi hoàn toàn có thể thử một góc nhìn khác. Tôi đã tìm kiếm các dạng xem khác có chứa các tham chiếu đến cả sys.sysrowsetsALUCOUNT và có nhiều thứ hiển thị trong danh sách, nhưng chỉ có hai cái là hứa hẹn:sys.internal_partitionssys.system_internals_partitions .

sys.internal_partitions

Tôi đã thử sys.internal_partitions đầu tiên:

 CHỌN * TỪ sys.internal_partitions AS p INNER JOIN sys.objects AS o ON p.object_id =o.object_id WHERE o.is_ms_shipped =0; 

Nhưng kế hoạch cũng không khả quan hơn (bấm vào để phóng to):

Lập kế hoạch cho sys.internal_partitions

Chỉ có hai lần quét đối với sys.sysrowsets lần này, nhưng việc quét dù sao cũng không liên quan vì truy vấn không đến gần tạo ra các hàng mà chúng tôi quan tâm. Chúng tôi chỉ thấy các hàng cho các đối tượng liên quan đến cột (như tài liệu đã nêu).

sys.system_internals_partitions

Hãy thử sys.system_internals_partitions . Tôi hơi cảnh giác về điều này, vì nó không được hỗ trợ (xem cảnh báo ở đây), nhưng hãy đợi tôi một chút:

 CHỌN * TỪ sys.system_internals_partitions AS p INNER JOIN sys.objects AS o ON p.object_id =o.object_id WHERE o.is_ms_shipped =0; 

Trong cơ sở dữ liệu có chỉ mục columnstore, có một quá trình quét đối với sys.sysschobjs , nhưng bây giờ chỉ có một quét chống lại sys.sysrowsets (bấm để phóng to):

Lập kế hoạch cho sys.system_internals_partitions, với các chỉ mục cột có sẵn

Nếu chúng tôi chạy cùng một truy vấn trong cơ sở dữ liệu mà không có chỉ mục columnstore, thì kế hoạch thậm chí còn đơn giản hơn, với tìm kiếm đối với sys.sysschobjs (bấm để phóng to):

Lập kế hoạch cho sys.system_internals_partitions, không có chỉ mục cột nào

Tuy nhiên, điều này không hoàn toàn những gì chúng ta đang theo đuổi, hoặc ít nhất không hoàn toàn là những gì Jake đang theo đuổi, bởi vì nó cũng bao gồm các đồ tạo tác từ các chỉ mục của Columnstore. Nếu chúng tôi thêm các bộ lọc này, đầu ra thực tế bây giờ khớp với truy vấn trước đó, đắt hơn nhiều của chúng tôi:

 CHỌN * TỪ sys.system_internals_partitions AS p INNER JOIN sys.objects AS o ON p.object_id =o.object_id WHERE o.is_ms_shipped =0 VÀ p.is_columnstore =0 VÀ p.is_orphaned =0; 

Như một phần thưởng, quét chống lại sys.sysschobjs đã trở thành một tìm kiếm ngay cả trong cơ sở dữ liệu với các đối tượng columnstore. Hầu hết chúng ta sẽ không nhận thấy sự khác biệt đó, nhưng nếu bạn đang ở trong một trường hợp giống như trường hợp của Jake, bạn chỉ có thể (nhấp để phóng to):

Kế hoạch đơn giản hơn cho sys.system_internals_partitions, với các bộ lọc bổ sung

sys.system_internals_partitions hiển thị một tập hợp cột khác với sys.partitions (một số khác hoàn toàn, một số khác có tên mới) vì vậy, nếu bạn đang sử dụng đầu ra ở phía dưới, bạn sẽ phải điều chỉnh cho phù hợp. Bạn cũng sẽ muốn xác thực rằng nó trả về tất cả thông tin bạn muốn trên các chỉ mục rowstore, bộ nhớ được tối ưu hóa và cột, và đừng quên về những đống phiền phức đó. Và cuối cùng, hãy sẵn sàng bỏ đi s trong internals rất nhiều lần.

Kết luận

Như tôi đã đề cập ở trên, chế độ xem hệ thống này không được hỗ trợ chính thức, vì vậy chức năng của nó có thể thay đổi bất cứ lúc nào; nó cũng có thể được di chuyển theo Kết nối quản trị viên chuyên dụng (DAC) hoặc bị xóa hoàn toàn khỏi sản phẩm. Vui lòng sử dụng phương pháp này nếu sys.partitions không hoạt động tốt cho bạn nhưng hãy đảm bảo rằng bạn có một kế hoạch dự phòng. Và đảm bảo rằng nó được ghi lại như một thứ mà bạn kiểm tra hồi quy khi bắt đầu thử nghiệm các phiên bản SQL Server trong tương lai hoặc sau khi bạn nâng cấp, đề phòng.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Cách lưu trữ lịch biểu của nhân viên trong cơ sở dữ liệu

  2. Cách chọn đúng loại dữ liệu

  3. Số lần xem và số liệu thống kê được lập chỉ mục

  4. Cách theo dõi những gì người dùng làm

  5. Sử dụng dữ liệu được bảo vệ bằng Kho khóa tùy chỉnh từ Linux