Я працюю над командою SQL Server, і, сподіваюсь, я можу прояснити декілька моментів у цій темі (я її раніше не бачив, тому мені шкода, що інженерна команда раніше цього не робила).
По- перше, не існує семантична різниця між select count(1) from table
VS. select count(*) from table
. Вони повертають однакові результати у всіх випадках (і це помилка, якщо ні). Як зазначається в інших відповідях, select count(column) from table
семантично відрізняється і не завжди повертає ті самі результати, що і count(*)
.
По-друге, що стосується продуктивності, то в SQL Server (і SQL Azure) важливі два аспекти: робота в компіляції та час роботи. Час роботи на компіляцію - це тривіально невелика кількість додаткової роботи в поточній реалізації. У деяких випадках відбувається розширення * на всі стовпці з подальшим скороченням до 1 стовпця, що виводиться через те, як деякі внутрішні операції працюють у прив'язці та оптимізації. Я сумніваюся, що він виявиться в будь-якому вимірюваному тесті, і він, швидше за все, загубиться в шумі всіх інших речей, що трапляються під кришками (таких як автоматична статистика, сеанси xevent, накладні сховища запитів, тригери тощо). Це, можливо, кілька тисяч додаткових інструкцій щодо процесора. Тому, count (1) робить трохи менше роботи під час компіляції (що, як правило, трапляється один раз, і план кешується через декілька наступних виконань). Під час виконання, якщо припустити, що плани є однаковими, не повинно бути ніякої вимірюваної різниці. (Один з попередніх прикладів показує різницю - це, швидше за все, пов'язано з іншими факторами на машині, якщо план однаковий).
Щодо того, як план потенційно може бути різним. Це вкрай малоймовірно, але це можливо в архітектурі поточного оптимізатора. Оптимізатор SQL Server працює як програма пошуку (подумайте: комп’ютерна програма, що грає в шахи, шукаючи різні альтернативи для різних частин запиту, і витрачає альтернативи, щоб знайти найдешевший план у розумні строки). Цей пошук має кілька обмежень щодо того, як він працює, щоб тримати завершення складання запитів у розумні строки. Для запитів, які виходять за межі найтривіальніших, існують фази пошуку, і вони мають справу з траншами запитів, виходячи з того, наскільки оптимізатор вважає, що запит може бути виконаний. Існує 3 основні фази пошуку, і кожна фаза може виконувати більш агресивну (дорогу) евристику, намагаючись знайти дешевший план, ніж будь-яке попереднє рішення. Зрештою, в кінці кожної фази відбувається процес прийняття рішень, який намагається визначити, чи повинен він повертати знайдений досі план чи слід продовжувати шукати. Цей процес використовує загальний час, витрачений на даний момент, відповідно до розрахункової вартості найкращого плану, знайденого до цього часу. Так, на різних машинах з різною швидкістю процесорів можна (хоч і рідко) отримувати різні плани за рахунок вичерпання часу на більш ранній фазі з планом порівняно з продовженням наступної фази пошуку. Існує також кілька подібних сценаріїв, пов’язаних із тимчасовим закінченням останньої фази та потенційним вичерпанням пам’яті на дуже, дуже дорогі запити, які споживають всю пам'ять на машині (як правило, це не проблема для 64-розрядних, але це викликало більшу проблему назад на 32-бітних серверах). Зрештою, якщо ви отримаєте інший план, продуктивність під час виконання буде відрізнятися. Я не '
Net-net: Будь ласка, використовуйте те, що ви хочете з двох, оскільки жодне з цих питань не має жодної практичної форми. (Є багато, набагато більших факторів, які впливають на продуктивність у SQL поза цією темою, якщо чесно).
Я сподіваюся, що це допомагає. Я написав розділ книги про те, як працює оптимізатор, але я не знаю, чи доцільно розмістити його тут (оскільки я все-таки отримую крихітні роялті від нього, я все-таки вірю). Тож замість публікації я опублікую посилання на розмову, яку я виклав у SQLBits у Великобританії про те, як оптимізатор працює на високому рівні, щоб ви могли детальніше ознайомитись з різними основними фазами пошуку, якщо хочете щоб дізнатися про це. Ось відео посилання: https://sqlbits.com/Sessions/Event6/inside_the_sql_server_query_optimizer