Я зауважую, що, коли трапляються події tempdb події (спричиняючи повільні запити), часто оцінки рядків відключаються для певного об'єднання. Я бачив, як події розливу відбуваються під час злиття та приєднання хешу, і вони часто збільшують тривалість виконання від 3 до 10 разів. Це питання стосується того, як поліпшити кошториси рядків, припускаючи, що це зменшить шанси на розлив подій.
Фактична кількість рядків 40 к.
Для цього запиту план показує неправильну оцінку рядків (11,3 рядків):
select Value
from Oav.ValueArray
where ObjectId = (select convert(bigint, Value) NodeId
from Oav.ValueArray
where PropertyId = 3331
and ObjectId = 3540233
and Sequence = 2)
and PropertyId = 2840
option (recompile);
Для цього запиту план показує хорошу оцінку рядків (56k рядків):
declare @a bigint = (select convert(bigint, Value) NodeId
from Oav.ValueArray
where PropertyId = 3331
and ObjectId = 3540233
and Sequence = 2);
select Value
from Oav.ValueArray
where ObjectId = @a
and PropertyId = 2840
option (recompile);
Чи можна додати статистику чи підказки для покращення оцінок рядків у першому випадку? Я спробував додати статистику з певними значеннями фільтра (властивість = 2840), але або не вдалося отримати правильну комбінацію, або, можливо, її ігнорують, оскільки ObjectId невідомий під час компіляції, і він може вибирати середнє значення для всіх ObjectIds.
Чи є режим, коли він спочатку здійснить запит зонда, а потім використає його для визначення оцінок рядків чи він повинен сліпо пролетіти?
Ця властивість має багато значень (40 к) для кількох об'єктів і нуль у переважній більшості. Я був би радий натяком, де можна було б вказати максимальну очікувану кількість рядків для заданого з'єднання. Це, як правило, непроста проблема, оскільки деякі параметри можуть визначатися динамічно як частина з'єднання або краще розміщуватись у представленні (немає підтримки змінних).
Чи є якісь параметри, які можна скорегувати, щоб мінімізувати ймовірність розливу до tempdb (наприклад, мінімум пам'яті на запит)? Надійний план не вплинув на кошторис.
Редагувати 2013.11.06 : Відповідь на коментарі та додаткову інформацію:
Ось зображення плану запитів. Попередження про кардинальність / шукати предикат з convert ():
За коментарем @Aaron Bertrand я спробував замінити convert () як тест:
create table Oav.SeekObject (
LookupId bigint not null primary key,
ObjectId bigint not null
);
insert into Oav.SeekObject (
LookupId, ObjectId
) VALUES (
1, 3540233
)
select Value
from Oav.ValueArray
where ObjectId = (select ObjectId
from Oav.SeekObject
where LookupId = 1)
and PropertyId = 2840
option (recompile);
Як дивна, але успішна цікава точка, також дозволила коротко замикати пошук:
select Value
from Oav.ValueArray
where ObjectId = (select ObjectId
from Oav.ValueArray
where PropertyId = 2840
and ObjectId = 3540233
and Sequence = 2)
and PropertyId = 2840
option (recompile);
Обидва перелічують правильний пошук ключів, але лише перший містить "Вихід" ObjectId. Я здогадуюсь, що вказує на те, що другий справді короткий замикання?
Чи може хтось перевірити, чи виконуються однорядні зонди, щоб допомогти з оцінкою рядків? Очевидно, що оптимізація обмежується лише оцінкою гістограми, коли однорядний пошук ПК може значно підвищити точність пошуку в гістограмі (особливо, якщо є потенціал розливу чи історія). Коли в цих реальних запитах є 10 цих підпоєднань, в ідеалі вони відбуватимуться паралельно.
Побічна примітка, оскільки sql_variant зберігає базовий тип (SQL_VARIANT_PROPERTY = BaseType) у самому полі, я б очікував, що перетворення () буде майже безцінним, доки воно "прямо" конвертоване (наприклад, не рядкове в десяткове, а швидше int до int або, можливо, int to bigint). Оскільки це невідомо під час компіляції, але може бути відомий користувачеві, можливо, функція "AssumeType (тип, ...)" для sql_variants дозволила б обробляти їх більш прозоро.
declare @a bigint =
як ви це зробили, здається для мене природним рішенням, чому це неприйнятно?
CONVERT()
в стовпцях, а потім приєднуватися до них. Це, звичайно, неефективно в більшості випадків. У цьому конкретному конвертується лише одне значення, тому, ймовірно, це не проблема, але які індекси у вас в таблиці? Проекти EAV зазвичай працюють добре, лише за умови належної індексації (що означає багато індексів у вузьких таблицях).