Ви можете отримати щось подібне до CARDINALITY
підказки Oracle, стратегічно використовуючи TOP
та визначену користувачем функцію, яку називають MANY()
розроблений Адамом Маханіком . Давайте опрацюємо кілька прикладів. Я використовую вільно доступну базу даних AdventureWorks. Припустимо, мені дійсно потрібно контролювати кількість рядків, повернених у th
похідній таблиці, у наступному запиті:
SELECT
p.Name
, th.ProductId
, th.Quantity
, th.ActualCost
FROM Production.Product p
INNER JOIN (
SELECT ProductId, Quantity, ActualCost
FROM Production.TransactionHistory
) th ON p.ProductID = th.ProductID;
Я маю оцінку 113443 рядків:
Якщо мені потрібно знизити оцінку, th
я можу використовувати TOP
разом із OPTIMIZE FOR
підказкою запит для встановлення мети рядка. Ось один із способів зробити це:
DECLARE @row_goal BIGINT = 9223372036854775807;
SELECT
p.Name
, th.ProductId
, th.Quantity
, th.ActualCost
FROM Production.Product p
INNER JOIN (
SELECT TOP (@row_goal) ProductId, Quantity, ActualCost
FROM Production.TransactionHistory
) th ON p.ProductID = th.ProductID
OPTION (OPTIMIZE FOR (@row_goal = 1));
Ми бачимо, що оцінка становить лише 1 ряд:
Я встановлюю @row_goal
максимально можливе BIGINT
значення, щоб уникнути зміни результатів. OPTIMIZE FOR
Підказка запиту інструктує оптимізатор оптимізатор запиту як якщо@row_goal
дорівнює 1. Я отримаю ті ж результати , але запит буде оптимізований по- різному.
Підвищення оцінки кардинальності складніше. Ми не можемо просто збільшити значення, TOP
оскільки оптимізатор зрозуміє, що він не поверне достатньо рядків. Однак ми можемо використовувати MANY()
функцію для додавання рядків до кошторису. Зауважте, що MANY()
функція завжди повертатиме 0 рядків, але оцінка рядка з неї змінюється з вхідним параметром. Припустимо, що вам потрібно збільшити оцінку рядків із похідної таблиці на 10X. Один із способів досягти цього:
SELECT
p.Name
, th.ProductId
, th.Quantity
, th.ActualCost
FROM Production.Product p
INNER JOIN (
SELECT TOP (9223372036854775807) ProductId, Quantity, ActualCost
FROM Production.TransactionHistory
LEFT OUTER JOIN dbo.Many(10) AS m ON 1=1
) th ON p.ProductID = th.ProductID;
Ми бачимо, що базова таблиця становить 10X:
Зайве TOP
було додано, щоб запобігти переміщенню таблиць оптимізатором. Без цьогоMANY()
функція може бути застосована до неправильного місця в плані.
Можна поєднати дві методики, якщо ви хочете точну переоцінку, а не просто множення кількості рядків на коефіцієнт. Наприклад, припустимо, що вам дійсно потрібна оцінка виведеної таблиці рівно 1000000 рядків. Один із способів досягти цього:
DECLARE @row_goal BIGINT = 9223372036854775807;
SELECT
p.Name
, th.ProductId
, th.Quantity
, th.ActualCost
FROM Production.Product p
INNER JOIN (
SELECT TOP (@row_goal) ProductId, Quantity, ActualCost
FROM Production.TransactionHistory
LEFT OUTER JOIN dbo.Many(10) AS m ON
1=1
) th ON p.ProductID = th.ProductID
OPTION (OPTIMIZE FOR (@row_goal = 1000000));
Ми бачимо, що оцінка становить 1000000 рядків:
Мені потрібно застерегти, що це передові методи, які часто не потрібні для оптимізації запитів. Якщо ви хочете дізнатися більше, я рекомендую переглянути цілі Clash of the Row, представлені Адамом Маханіком.
dbo.Many функція
-- By Adam Machanic, reproduced with permission
IF EXISTS (SELECT * FROM sys.objects WHERE name = 'Many' AND OBJECT_SCHEMA_NAME(object_id) = 'dbo')
DROP FUNCTION dbo.Many
GO
CREATE FUNCTION dbo.Many(@n INT)
RETURNS TABLE AS
RETURN
(
WITH
a(x) AS
(
SELECT
*
FROM
(
VALUES
(1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
(1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
(1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
(1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
(1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
(1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
(1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
(1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
(1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
(1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
(1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
(1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
(1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
(1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
(1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
(1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
(1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
(1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
(1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
(1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
(1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
(1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
(1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
(1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
(1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
(1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
(1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
(1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
(1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
(1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
(1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
(1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
(1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
(1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
(1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
(1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
(1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
(1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
(1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
(1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
(1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
(1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
(1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
(1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
(1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
(1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
(1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
(1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
(1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
(1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
(1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
(1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
(1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
(1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
(1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
(1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
(1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
(1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
(1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
(1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
(1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
(1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
(1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
(1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1)
) AS x0(x)
)
SELECT TOP(@n)
1 AS x
FROM
a AS a1,
a AS a2
WHERE
a1.x % 2 = 0
)
GO