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

3 mẹo hàng đầu bạn cần biết để viết chế độ xem SQL nhanh hơn

Bạn hay thù? Chế độ xem SQL Server đã từng là chủ đề của các cuộc tranh luận sôi nổi khi tôi sử dụng SQL Server trong năm đầu tiên. Họ nói rằng nó rất tệ vì nó chậm. Nhưng hôm nay thì sao?

Bạn có đang trên cùng con thuyền với tôi nhiều năm trước không? Sau đó, hãy tham gia cùng tôi trong hành trình này để làm sáng tỏ vấn đề thực sự về các dạng xem SQL để bạn có thể viết chúng nhanh nhất có thể.

Các khung nhìn SQL là các bảng ảo. Các bản ghi trong một dạng xem là kết quả của một truy vấn bên trong nó. Bất cứ khi nào các bảng cơ sở được sử dụng trong dạng xem được cập nhật, nó cũng sẽ cập nhật dạng xem đó. Bạn cũng có thể CHÈN, CẬP NHẬT và XÓA bản ghi trong một dạng xem dưới dạng bảng trong một số trường hợp. Mặc dù bản thân tôi chưa thử điều này.

Tương tự với bảng, bạn có thể TẠO, THAY THẾ hoặc XÓA chế độ xem. Bạn thậm chí có thể tạo một chỉ mục, với một số hạn chế.

Lưu ý rằng tôi đã sử dụng SQL Server 2019 trong các mã mẫu.

1. Biết cách sử dụng đúng và không đúng các chế độ xem SQL

Đầu tiên, những điều cơ bản.

Dạng xem SQL dùng để làm gì?

Nó là tối quan trọng. Nếu bạn sử dụng nó như một cái búa vào một cái tuốc nơ vít, hãy quên đi các chế độ xem SQL nhanh hơn. Đầu tiên, hãy nhớ lại cách sử dụng thích hợp:

  • Để tập trung, đơn giản hóa và tùy chỉnh nhận thức của mỗi người dùng về cơ sở dữ liệu.
  • Để cho phép người dùng truy cập vào thông tin duy nhất mà họ cần xem vì lý do bảo mật.
  • Để cung cấp khả năng tương thích ngược với một bảng cũ hoặc một lược đồ cũ để không làm hỏng các ứng dụng phụ thuộc. Việc này chỉ là tạm thời cho đến khi tất cả các thay đổi cần thiết hoàn tất.
  • Để phân vùng dữ liệu đến từ các máy chủ khác nhau. Do đó, chúng xuất hiện như thể chúng là một bảng từ một máy chủ hoặc phiên bản.

Cách KHÔNG sử dụng dạng xem SQL Server?

  • Sử dụng lại chế độ xem trong một chế độ xem khác sẽ được sử dụng lại trong một chế độ xem khác. Trong ngắn hạn, các quan điểm lồng ghép sâu sắc. Việc sử dụng lại mã có một số hạn chế trong trường hợp này.
  • Tiết kiệm khi gõ phím. Nó liên quan đến cái đầu tiên, giúp giảm áp lực ngón tay và có vẻ như tăng tốc quá trình viết mã.

Việc sử dụng chế độ xem không đúng cách, nếu được cho phép, sẽ che khuất lý do thực sự khiến bạn tạo chế độ xem. Như bạn sẽ thấy ở phần sau, lợi ích thực sự lớn hơn lợi ích được nhận thức của việc sử dụng không đúng cách.

Ví dụ

Hãy xem một ví dụ từ Microsoft. vE Employee xem từ AdventureWorks . Đây là mã:

-- Employee names and basic contact information
CREATE VIEW [HumanResources].[vEmployee] 
AS 
SELECT 
    e.[BusinessEntityID]
    ,p.[Title]
    ,p.[FirstName]
    ,p.[MiddleName]
    ,p.[LastName]
    ,p.[Suffix]
    ,e.[JobTitle]  
    ,pp.[PhoneNumber]
    ,pnt.[Name] AS [PhoneNumberType]
    ,ea.[EmailAddress]
    ,p.[EmailPromotion]
    ,a.[AddressLine1]
    ,a.[AddressLine2]
    ,a.[City]
    ,sp.[Name] AS [StateProvinceName] 
    ,a.[PostalCode]
    ,cr.[Name] AS [CountryRegionName] 
    ,p.[AdditionalContactInfo]
FROM [HumanResources].[Employee] e
    INNER JOIN [Person].[Person] p
 ON p.[BusinessEntityID] = e.[BusinessEntityID]
    INNER JOIN [Person].[BusinessEntityAddress] bea 
        ON bea.[BusinessEntityID] = e.[BusinessEntityID] 
    INNER JOIN [Person].[Address] a 
        ON a.[AddressID] = bea.[AddressID]
    INNER JOIN [Person].[StateProvince] sp 
        ON sp.[StateProvinceID] = a.[StateProvinceID]
    INNER JOIN [Person].[CountryRegion] cr 
        ON cr.[CountryRegionCode] = sp.[CountryRegionCode]
    LEFT OUTER JOIN [Person].[PersonPhone] pp
        ON pp.BusinessEntityID = p.[BusinessEntityID]
    LEFT OUTER JOIN [Person].[PhoneNumberType] pnt
        ON pp.[PhoneNumberTypeID] = pnt.[PhoneNumberTypeID]
    LEFT OUTER JOIN [Person].[EmailAddress] ea
        ON p.[BusinessEntityID] = ea.[BusinessEntityID];
GO

Mục đích của quan điểm này tập trung vào thông tin cơ bản của nhân viên. Nếu nhân viên nhân sự cần, nó có thể được hiển thị trên một trang web. Nó có được sử dụng lại trong các chế độ xem khác không?

Hãy thử điều này:

  1. Trong SQL Server Management Studio , hãy tìm AdventureWorks cơ sở dữ liệu.
  2. Mở rộng Thư mục chế độ xem và tìm kiếm [HumanResources]. [vErantyee].
  3. Nhấp chuột phải vào nó và chọn Xem phần phụ thuộc .

Nếu bạn thấy một chế độ xem khác tùy thuộc vào chế độ xem này, sau đó phụ thuộc vào một chế độ xem khác, Microsoft đã cho chúng ta một ví dụ xấu. Nhưng sau đó, không có chế độ xem phụ thuộc nào khác.

Hãy chuyển sang phần tiếp theo.

2. Gỡ bỏ lầm tưởng về chế độ xem SQL

Khi SQL Server xử lý một CHỌN từ một chế độ xem , nó đánh giá mã trong chế độ xem TRƯỚC KHI nó xử lý với mệnh đề WHERE hoặc bất kỳ phép nối nào trong truy vấn bên ngoài. Với nhiều bảng được tham gia hơn, nó sẽ chậm hơn so với một CHỌN từ các bảng cơ sở với cùng một kết quả.

Ít nhất, đó là những gì tôi đã được nói khi bắt đầu sử dụng SQL. Cho dù đó có phải là huyền thoại hay không, chỉ có một cách để tìm hiểu. Hãy chuyển sang một ví dụ thực tế.

Cách thức hoạt động của chế độ xem SQL

Microsoft đã không để chúng ta trong bóng tối để tranh luận không ngừng. Chúng tôi có các công cụ để xem cách hoạt động của các truy vấn, chẳng hạn như IO THỐNG KÊ Kế hoạch thực thi thực tế . Chúng tôi sẽ sử dụng chúng trong tất cả các ví dụ của chúng tôi. Hãy có cái đầu tiên.

USE AdventureWorks
GO

SELECT * FROM HumanResources.vEmployee e
WHERE e.BusinessEntityID = 105

Để xem điều gì đang xảy ra khi SQL Server xử lý chế độ xem, hãy cùng kiểm tra Kế hoạch thực thi thực tế trong Hình 1. Chúng tôi so sánh nó với mã TẠO CHẾ ĐỘ XEM cho vEFastee trong phần trước.

Như bạn có thể thấy, các nút đầu tiên được SQL Server xử lý là các nút sử dụng INNER JOIN. Sau đó, nó sẽ tiếp tục xử lý các THAM GIA TRÁI RA.

Vì chúng ta không thể thấy nút Bộ lọc ở bất kỳ đâu đối với mệnh đề WHERE, nên nó phải ở một trong các nút đó. Nếu bạn kiểm tra thuộc tính của tất cả các nút, bạn sẽ thấy mệnh đề WHERE được xử lý trong bảng Nhân viên. Tôi đã đặt nó trong một hộp trong Hình 1. Để chứng minh rằng nó ở đó, hãy xem Hình 2 để biết Thuộc tính của nút đó:

Phân tích

Vì vậy, đã có câu lệnh SELECT trong vEFastee chế độ xem đã được đánh giá hoặc xử lý TRƯỚC KHI áp dụng mệnh đề WHERE? Kế hoạch Thực thi cho thấy rằng nó đã không. Nếu đúng như vậy, nó sẽ xuất hiện gần nút CHỌN nhất.

Những gì tôi được kể là một huyền thoại. Tôi đã tránh điều gì đó tốt vì hiểu nhầm về cách sử dụng chế độ xem SQL thích hợp.

Bây giờ chúng ta đã biết cách SQL Server xử lý một CHỌN từ một dạng xem , câu hỏi vẫn là:Nó có chậm hơn so với việc không sử dụng chế độ xem không?

CHỌN TỪ Chế độ xem so với CHỌN TỪ Bảng Cơ sở - Cái nào sẽ chạy nhanh hơn?

Trước tiên, chúng ta cần trích xuất câu lệnh SELECT bên trong vEFastee xem và tạo ra kết quả giống như chúng tôi đã có khi sử dụng chế độ xem. Đoạn mã dưới đây hiển thị cùng một mệnh đề WHERE:

USE AdventureWorks
GO

-- SELECT FROM a view
SELECT * FROM HumanResources.vEmployee e
WHERE e.BusinessEntityID = 105

-- SELECT FROM Base Tables
SELECT 
    e.[BusinessEntityID]
    ,p.[Title]
    ,p.[FirstName]
    ,p.[MiddleName]
    ,p.[LastName]
    ,p.[Suffix]
    ,e.[JobTitle]  
    ,pp.[PhoneNumber]
    ,pnt.[Name] AS [PhoneNumberType]
    ,ea.[EmailAddress]
    ,p.[EmailPromotion]
    ,a.[AddressLine1]
    ,a.[AddressLine2]
    ,a.[City]
    ,sp.[Name] AS [StateProvinceName] 
    ,a.[PostalCode]
    ,cr.[Name] AS [CountryRegionName] 
    ,p.[AdditionalContactInfo]
FROM [HumanResources].[Employee] e
    INNER JOIN [Person].[Person] p
	ON p.[BusinessEntityID] = e.[BusinessEntityID]
    INNER JOIN [Person].[BusinessEntityAddress] bea 
        ON bea.[BusinessEntityID] = e.[BusinessEntityID] 
    INNER JOIN [Person].[Address] a 
        ON a.[AddressID] = bea.[AddressID]
    INNER JOIN [Person].[StateProvince] sp 
        ON sp.[StateProvinceID] = a.[StateProvinceID]
    INNER JOIN [Person].[CountryRegion] cr 
        ON cr.[CountryRegionCode] = sp.[CountryRegionCode]
    LEFT OUTER JOIN [Person].[PersonPhone] pp
        ON pp.BusinessEntityID = p.[BusinessEntityID]
    LEFT OUTER JOIN [Person].[PhoneNumberType] pnt
        ON pp.[PhoneNumberTypeID] = pnt.[PhoneNumberTypeID]
    LEFT OUTER JOIN [Person].[EmailAddress] ea
        ON p.[BusinessEntityID] = ea.[BusinessEntityID]
WHERE e.BusinessEntityID = 105

Sau đó, chúng tôi kiểm tra IO THỐNG KÊ và thực hiện So sánh kế hoạch trình chiếu . Một truy vấn từ một dạng xem sẽ cần bao nhiêu tài nguyên so với truy vấn từ các bảng cơ sở? Xem Hình 3.

Ở đây, truy vấn từ một khung nhìn hoặc các bảng cơ sở sẽ sử dụng cùng một lượt đọc logic. Cả hai đều sử dụng trang 19 * 8KB. Dựa trên điều này, đó là sự ràng buộc về việc ai nhanh hơn. Nói cách khác, việc sử dụng chế độ xem sẽ không ảnh hưởng đến hiệu suất. Hãy so sánh Kế hoạch thực thi thực tế của cả hai bằng cách sử dụng So sánh kế hoạch :

Bạn có thấy phần bóng mờ của sơ đồ không? Còn về QueryPlanHash của cả hai? Vì cả hai truy vấn đều có QueryPlanHash bằng nhau và các hoạt động giống nhau, chế độ xem hoặc bảng cơ sở sẽ được SQL Server xử lý giống nhau .

Các lần đọc logic giống nhau và cùng một kế hoạch của mẫu cho chúng ta biết rằng cả hai sẽ thực hiện như nhau. Do đó, việc có số lần đọc logic cao sẽ làm cho truy vấn của bạn chạy chậm cho dù bạn có sử dụng chế độ xem hay không. Biết thực tế này sẽ giúp bạn khắc phục sự cố và làm cho chế độ xem của bạn chạy nhanh hơn.

Rất tiếc, có một số tin xấu.

Nối chế độ xem SQL vào bảng

Những gì bạn đã thấy trước đó là một CHỌN từ một chế độ xem không có liên kết nào trong đó. Tuy nhiên, điều gì sẽ xảy ra nếu bạn tham gia một bảng để xem?

Hãy xem lại một ví dụ khác. Lần này, chúng tôi sử dụng vSalesPerson xem trong AdventureWorks - danh sách nhân viên bán hàng với thông tin liên hệ và hạn ngạch bán hàng. Một lần nữa, chúng tôi so sánh câu lệnh với một câu lệnh SELECT từ các bảng cơ sở:

-- get the total sales orders for each salesperson
-- using the view joined with SalesOrderHeader
SELECT 
 sp.FirstName
,sp.MiddleName
,sp.LastName
,SUM(soh.TotalDue) AS TotalSalesOrders
FROM Sales.vSalesPerson sp
INNER JOIN Sales.SalesOrderHeader soh ON sp.BusinessEntityID = soh.SalesPersonID
GROUP BY sp.LastName, sp.MiddleName, sp.FirstName

-- using base tables
SELECT
 p.FirstName
,p.MiddleName
,p.LastName
,SUM(soh.TotalDue) AS TotalSalesOrders
FROM sales.SalesPerson sp
INNER JOIN Person.Person p ON sp.BusinessEntityID = P.BusinessEntityID
INNER JOIN Sales.SalesOrderHeader soh ON sp.BusinessEntityID = soh.SalesPersonID
GROUP BY p.LastName, p.MiddleName, p.FirstName 

Nếu bạn nghĩ rằng nó cũng sẽ giống nhau, hãy kiểm tra IO THỐNG KÊ:

Ngạc nhiên? Tham gia vSalesPerson xem bằng SalesOrderHeader bảng cần tài nguyên lớn (28,240 x 8KB) so với việc chỉ sử dụng bảng cơ sở (774 x 8KB). Cũng lưu ý rằng nó bao gồm một số bảng mà chúng tôi không cần (các bảng trong hộp màu đỏ). Hãy để những lần đọc logic cao hơn trên SalesOrderHeader khi sử dụng chế độ xem.

Nhưng nó không kết thúc ở đó.

Kế hoạch Thực thi Thực tế Tiết lộ Thêm

Lưu ý Kế hoạch thực thi thực tế của truy vấn đến các bảng cơ sở:

Hình minh họa dường như cho thấy một Kế hoạch Thực thi khá bình thường. Nhưng hãy kiểm tra một cái với chế độ xem:

Kế hoạch thực hiện trong Hình 7 trùng với IO THỐNG KÊ trong Hình 5. Chúng ta có thể thấy các bảng mà chúng ta không cần từ khung nhìn. Ngoài ra còn có Tra cứu khóa nút có ước tính hàng giảm hơn một nghìn bản ghi so với các hàng thực tế. Cuối cùng, một cảnh báo trong nút CHỌN cũng xuất hiện. Nó có thể là gì?

Đó là gì TooiveGrant cảnh báo trong nút CHỌN?

Cấp thừa xảy ra khi bộ nhớ được sử dụng tối đa quá nhỏ so với bộ nhớ được cấp. Trong trường hợp này, 1024KB đã được cấp, nhưng chỉ có 16KB được sử dụng.

Cấp bộ nhớ là lượng bộ nhớ ước tính tính bằng KB cần thiết để chạy gói.

Đó có thể là các ước tính sai trong Tra cứu khóa và / hoặc việc bao gồm các bảng mà chúng tôi không cần trong kế hoạch đã gây ra điều này. Ngoài ra, bộ nhớ được cấp quá nhiều có thể gây ra hiện tượng chặn. 1008KB còn lại có thể hữu ích cho các hoạt động khác.

Cuối cùng, đã xảy ra sự cố khi bạn tham gia chế độ xem với một bảng. Chúng tôi không phải giải quyết những vấn đề này nếu chúng tôi truy vấn từ các bảng cơ sở.

Bài học rút ra

Đó là một lời giải thích dài. Tuy nhiên, chúng tôi biết rằng các lượt xem không được đánh giá hoặc xử lý TRƯỚC KHI một mệnh đề WHERE hoặc các phép nối trong truy vấn bên ngoài được đánh giá. Chúng tôi cũng đã chứng minh rằng cả hai sẽ hoạt động như nhau.

Mặt khác, có một trường hợp khi chúng ta nối một chế độ xem với một bảng. Nó sử dụng kết hợp các bảng mà chúng tôi không cần từ chế độ xem. Chúng vô hình đối với chúng tôi trừ khi chúng tôi kiểm tra IO THỐNG KÊ và Kế hoạch Thực thi Thực tế. Tất cả đều có thể ảnh hưởng đến hiệu suất và các vấn đề có thể xảy ra.

Do đó:

  • Chúng ta nên biết cách các truy vấn, bao gồm cả chế độ xem, hoạt động từ bên trong.
  • IO THỐNG KÊ và Kế hoạch thực thi thực tế sẽ tiết lộ cách hoạt động của các truy vấn và chế độ xem.
  • Chúng ta không thể chỉ nối một chế độ xem vào một bảng và sử dụng lại nó một cách bất cẩn . Luôn kiểm tra IO THỐNG KÊ và Kế hoạch thực thi thực tế! Thay vì sử dụng lại các chế độ xem và lồng chúng để tăng năng suất mã hóa "được cải thiện", tôi sử dụng IntelliSense và công cụ hoàn thành mã như SQL Complete.

Sau đó, chúng tôi có thể chắc chắn rằng không viết các chế độ xem sẽ có kết quả chính xác nhưng chạy như một con ốc sên.

3. Thử Chế độ xem được lập chỉ mục

Chế độ xem được lập chỉ mục là những gì tên của nó. Nó có thể tăng hiệu suất cho các câu lệnh SELECT. Nhưng giống như chỉ mục bảng, nó có thể ảnh hưởng đến hiệu suất nếu các bảng cơ sở lớn và được cập nhật liên tục.

Để xem các chế độ xem được lập chỉ mục có thể cải thiện hiệu suất truy vấn như thế nào, hãy cùng kiểm tra vStateProvinceCountryRegion xem trong AdventureWorks . Chế độ xem được lập chỉ mục trên StateProvinceID CountryRegionCode . Nó là một chỉ mục được phân nhóm, duy nhất.

Hãy so sánh IO THỐNG KÊ của chế độ xem không có chỉ mục và có chỉ mục. Với điều này, chúng tôi tìm hiểu máy chủ SQL của chúng tôi sẽ đọc bao nhiêu trang 8KB:

Hình cho thấy rằng có một chỉ mục trong vStateProvinceCountryRegion chế độ xem giảm một nửa số lần đọc logic. Nó cải thiện 50% so với không có chỉ mục.

Điều đó thật tốt khi nghe.

Tuy nhiên, một lần nữa, đừng thêm chỉ mục vào chế độ xem của bạn một cách bất cẩn. Bên cạnh việc có một danh sách dài các quy tắc nghiêm ngặt để có 1 chỉ mục nhóm, duy nhất, nó có thể ảnh hưởng đến hiệu suất, giống như việc thêm chỉ mục vào bảng một cách nhanh chóng. Ngoài ra, hãy kiểm tra IO THỐNG KÊ nếu có giảm số lần đọc logic sau khi thêm chỉ mục.

Bài học rút ra

Như chúng ta đã thấy trong ví dụ của mình, các chế độ xem được lập chỉ mục có thể cải thiện hiệu suất các chế độ xem SQL.

Mẹo THƯỞNG

Cũng giống như bất kỳ truy vấn nào khác, các dạng xem SQL sẽ chạy nhanh nếu:

  • Số liệu thống kê được cập nhật
  • Các chỉ mục bị thiếu được thêm vào
  • Các chỉ mục được chống phân mảnh
  • Các chỉ mục đã sử dụng đúng FILLFACTOR

Kết luận

Chế độ xem SQL tốt hay xấu?

Các dạng xem SQL sẽ tốt nếu chúng ta viết chúng một cách chính xác và kiểm tra xem chúng sẽ được xử lý như thế nào. Chúng tôi có các công cụ như STATISTICS IO và Actual Execution Plan - hãy sử dụng chúng! Các chế độ xem được lập chỉ mục cũng có thể cải thiện hiệu suất.

Như bài đăng này? Hãy chia sẻ tình yêu trên nền tảng mạng xã hội yêu thích của bạn.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Mẹo lưu trữ bản sao lưu DB theo tỷ lệ thời gian của bạn trên đám mây

  2. Cập nhật tự động cho thống kê có thể ảnh hưởng đến hiệu suất truy vấn như thế nào

  3. Khung của một Apache Spark Job Run!

  4. Tùy chọn điều chỉnh hiệu suất cơ sở dữ liệu Azure SQL

  5. Hiểu biết về làm lại nhóm nhật ký so với tệp và thành viên