Sơ đồ đủ điều kiện cần thiết để tái sử dụng kế hoạch truy vấn?


7

Trong khi đọc bài viết này về Kế hoạch bộ đệm trong máy chủ SQL, tôi đã bắt gặp một mẩu tin mà tôi không biết:

... Để sử dụng lại, điều cần thiết là các đối tượng mà các tham chiếu hàng loạt không yêu cầu độ phân giải tên. Ví dụ: Sales.SalesOrderDetail không yêu cầu phân giải tên, trong khi SalesOrderDetail thì có vì có thể có các bảng có tên SalesOrderDetail trong nhiều lược đồ. Nói chung, tên đối tượng hai phần (nghĩa là lược đồ.object) cung cấp nhiều cơ hội hơn cho việc sử dụng lại kế hoạch.

Tôi đang tìm kiếm một số giải thích về tầm quan trọng của việc sử dụng tên đối tượng hai phần, vì "Nói chung, tên đối tượng hai phần cung cấp nhiều cơ hội hơn cho việc sử dụng lại kế hoạch.", Nhưng nó bắt đầu bằng cách nói rằng nó cần thiết.

Cụ thể hơn, hầu hết các thủ tục được lưu trữ mà tôi xử lý đều nằm trong lược đồ dbo và chỉ tham chiếu các đối tượng dbo, mà không chỉ định tiền tố dbo. Chúng có bị ngăn không cho sử dụng lại các gói truy vấn được lưu trong bộ nhớ cache, ngay cả với mọi thứ sử dụng lược đồ mặc định không?

Câu trả lời:


7

Đối với một kế hoạch được sử dụng lại tất cả các thuộc tính trong sys.dm_exec_plan_attributesđó is_cache_key=1phải giống nhau. Một danh sách này là dưới đây.

acceptable_cursor_options
compat_level
date_first
date_format
dbid
dbid_execute
is_replication_specific
language_id
merge_action_type
objectid
optional_clr_trigger_dbid
optional_clr_trigger_objid
optional_spid
required_cursor_options
set_options
status
user_id

Một trong những ảnh hưởng bằng cách sử dụng hai tên phần là user_id

Nếu bạn thử những điều sau dưới thông tin đăng nhập của người dùng với lược đồ mặc định dbo

DBCC FREEPROCCACHE;

CREATE TABLE dbo.FooBar(X int);

EXEC('SELECT * FROM FooBar');
EXEC('SELECT * FROM FooBar');

EXEC('SELECT * FROM dbo.FooBar');
EXEC('SELECT * FROM dbo.FooBar');

Và sau đó thực hiện các truy vấn sau đây

SELECT usecounts,
       text,
       value AS [user_id] 
FROM sys.dm_exec_cached_plans
CROSS APPLY sys.dm_exec_sql_text(plan_handle)
CROSS APPLY sys.dm_exec_plan_attributes(plan_handle) AS epa
WHERE text LIKE 'SELECT * FROM %FooBar'  and attribute='user_id'

Bạn sẽ thấy kết quả như sau

usecounts   text                                user_id
----------- ----------------------------------- -------
2           SELECT * FROM dbo.FooBar            -2
2           SELECT * FROM FooBar                1 

Điều này cho thấy cả hai kế hoạch đã được sử dụng lại khi câu lệnh giống hệt được chạy lần thứ hai. Các tài liệu cho sys.dm_exec_plan_attribut giải thích chouser_id

Giá trị -2 chỉ ra rằng lô được gửi không phụ thuộc vào độ phân giải tên ẩn và có thể được chia sẻ giữa những người dùng khác nhau. Đây là phương pháp ưa thích. Bất kỳ giá trị nào khác đại diện cho ID người dùng của người dùng gửi truy vấn trong cơ sở dữ liệu.

Điều này dường như là không chính xác! Dường như từ thử nghiệm của tôi, giá trị mà nó thực sự sử dụng cho user_idtrường hợp thứ hai là schema_idlược đồ mặc định cho người dùng thực thi thay vì định danh cho người dùng cụ thể đó. Chạy lại bốn EXECcâu lệnh dưới một thông tin đăng nhập khác với lược đồ mặc định "dbo" đưa ra.

usecounts   text                                user_id
----------- ----------------------------------- -------
4           SELECT * FROM dbo.FooBar            -2
4           SELECT * FROM FooBar                1 

Hiển thị các gói cho cả hai phiên bản truy vấn có thể được sử dụng lại giữa những người dùng. Cuối cùng chạy lại bốn EXECcâu lệnh dưới lần đăng nhập thứ ba với lược đồ mặc định "khách" đưa ra.

usecounts   text                                user_id
----------- ----------------------------------- -------
6           SELECT * FROM dbo.FooBar            -2
4           SELECT * FROM FooBar                1
2           SELECT * FROM FooBar                2

Cho thấy rằng kế hoạch cho dbotruy vấn đủ điều kiện đã được chia sẻ thành công giữa những người dùng với các lược đồ mặc định khác nhau nhưng truy vấn không đủ điều kiện lược đồ cần một kế hoạch mới được biên dịch.

Nếu bạn không thấy chia sẻ này xảy ra đảm bảo rằng tất cả các thông tin đăng nhập bạn đang thử nghiệm có cùng set_options, language_id, date_first, date_formatvì đây là một trong những chìa khóa bộ nhớ cache được liệt kê ở đầu và bất kỳ sự khác biệt trong những sẽ ngăn chặn các kế hoạch được tái sử dụng giữa các phiên.


@Bort - Thật ra tôi vừa nhận ra rằng nó phụ thuộc vào lược đồ mặc định chứ không chỉ user_id. Trong thử nghiệm ban đầu của tôi, tôi đã có người dùng thứ hai WITH DEFAULT_SCHEMA=[guest]. Miễn là hai người dùng khác nhau có cùng một lược đồ mặc định, có vẻ như họ có thể chia sẻ các gói của nhau.
Martin Smith
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.