Добрий, поганий або байдужий: ДЕ 1 = 1


14

З огляду на це запитання в reddit, я очистив запит, щоб вказати, де проблема в запиті. Я спочатку використовую кому і WHERE 1=1щоб полегшити модифікацію запитів, тому мої запити, як правило, закінчуються так:

SELECT 
     C.CompanyName
    ,O.ShippedDate
    ,OD.UnitPrice
    ,P.ProductName
FROM 
               Customers       as C
    INNER JOIN Orders          as O  ON C.CustomerID = O.CustomerID
    INNER JOIN [Order Details] as OD ON O.OrderID    = OD.OrderID
    INNER JOIN Products        as P  ON P.ProductID  = OD.ProductID
Where 1=1
--  AND O.ShippedDate Between '4/1/2008' And '4/30/2008'
    And P.productname = 'TOFU'
Order By C.CompanyName

Хтось в основному сказав, що 1 = 1, як правило, ледачий і поганий у виконанні .

Зважаючи на те, що я не хочу "передчасно оптимізувати" - я хочу дотримуватися належної практики. Раніше я розглядав плани запитів, але, як правило, лише для того, щоб дізнатися, які індекси я можу додати (або відкоригувати), щоб мої запити працювали швидше.

Тоді питання справді ... чи Where 1=1спричиняє погані речі? А якщо так, то як я можу це сказати?

Незначна редакція: Я також завжди "припускав", що 1=1було б оптимізовано, або, в гіршому випадку, мізерно. Ніколи не завадить ставити під сумнів мантру, наприклад "Гото - це зло" чи "Передчасна оптимізація ..." чи інші припущені факти. Не був впевнений, чи 1=1 ANDреально це вплине на плани запитів чи ні. А як щодо підзапитів? CTE? Процедури?

Я не хочу оптимізувати, якщо це не потрібно ... але якщо я роблю щось, що насправді є "поганим", я б хотів мінімізувати ефекти або змінити, де це можливо.


2
Ні, не буде. Окрім кількох мікросекунд для оптимізатора для усунення надмірної умови. Ви краще зосередитись на тому, що літерали про дату не будуть неоднозначними.
ypercubeᵀᴹ

Як сказав @ypercube, це не має ніякого значення. Оптимізатор запитів повинен мати шматок ****, щоб подібна річ не мала ніякого значення;)
Philᵀᴹ

4
Не вірте всьому, що ви читаєте на reddit. Будь ласка.
Аарон Бертран

1
@AaronBertrand Я беру все з зерном солі, поки не пережив це з перших рук. Я все одно займусь питанням, яке звучить правдоподібно, і я побачу, чи є в ньому правда, особливо коли це стосується моєї щоденної роботи.
WernerCD

4
Там зерна солі, тоді вміст солі у всьому океані скидається поверх вашої офісної будівлі: P
Philᵀᴹ

Відповіді:


13

Сервер SQL аналізатороптимізатор має функцію під назвою "Постійне складання", яка виключає тавтологічні вирази з запиту.
Якщо ви подивитесь на план виконання, ніде в предикатах ви не побачите, що цей вираз з’явиться. Це означає, що постійне складання виконується так чи інакше під час компіляції з цієї та інших причин, і це не впливає на ефективність запитів.

Додаткову інформацію див. У розділі Оцінка постійного складання та вираження під час оцінки кардинальності .


Це, мабуть, складено далеко, тому що це відомий зразок для об'єднання полів.
jcolebrand

Ні, він складений далеко, тому що він є тавтологічним. Він би працював так само, як і з 2736 = 2736, що не так часто, як 1 = 1. Те ​​саме стосується суперечностей. У цьому випадку функція називається "виявлення протиріччя".
spaghettidba

Яка частина "відомого шаблону" означала "має бути 1 = 1"?
jcolebrand

9

Додавання надлишкового предиката може змінити SQL Server.

На планах виконання нижче зауважте, що @1у першому плані порівняно з буквальним 'foo'у другому плані.

введіть тут опис зображення

Це вказує на те, що SQL Server вважав першим запитом просту параметризацію для сприяння повторному використанню плану виконання - однак порівняння двох констант запобігає цьому у другому випадку.

Перелік умов, які перешкоджають простій параметризації (раніше відомі як автоматична параметризація), можна знайти в Додатку А до програми кешування технічних документів Microsoft:

проста параметризація - це взагалі не те, на що ви все-таки повинні покладатися. Набагато краще явно параметризувати ваші запити.


4

У будь-яких сучасних RDBMS (включаючи Oracle, Microsoft SQL Server та PostgreSQL - я впевнений у цьому) це не вплине на продуктивність.

Як хтось зазначив, це вплине лише на етап планування запитів. Отже різниця буде помітна лише тоді, коли ви запустите тисячі ітерацій спрощеного запиту, який не повертає жодних даних, як цей:

SELECT 1 FROM empty_table; -- run this 10 000 times.

SELECT 1 FROM empty_table WHERE 1=1; -- run this 10 000 times and compare.

Для мене на PostgreSQL 9.0 це видно лише 10000 ітерацій:

filip@srv:~$ pgquerybench.pl -h /var/run/postgresql/ -q "select 1 from never where 1=1" -q "select 1 from never" -i 10000
Iterations: 10000
Query:   select 1 from never where 1=1
Total:   2.952 s
Average: 0.295 ms
Query:   select 1 from never
Total:   2.850 s
Average: 0.285 ms

0

Це може бути "проблемою" для Oracle, коли ви використовуєте параметр бази даних cursor_sharing. Якщо для цього встановлено значення "примусити", воно змінить усі оператори SQL. Усі "константи" в запитах будуть замінені змінними прив'язки (наприклад, 1 =>: SYS_0).

Цей варіант був введений для боротьби з деякими ледачими розробниками. З іншого боку, це також може зашкодити іншим ледачим розробникам. Але ризик не надто високий. Починаючи з 11 г, він має функцію прививки змінного вигляду.


Чи можете ви уточнити, що "З 11g він має функцію прив'язки змінних peeking." засоби?
ypercubeᵀᴹ

@ypercube "Прив’язати перегляд змінного" означає, що оптимізатор буде спостерігати за фактичними значеннями змінних змінних та використовувати статистику даних для повторної оцінки та, можливо, відновлення плану виконання запиту. Я сумніваюся, що зазирвання матиме будь-який вплив на конструкцію, про яку йдеться, хоча це не залежить від статистики даних.
мустаччо
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.