Самый быстрый способ подсчета различных значений в столбце, включая значения NULL

Операция Transact-Sql Count Distinct подсчитывает все ненулевые значений в столбце. Мне нужно подсчитать количество различных значений в столбце в наборе таблиц, включая значения NULL (поэтому, если в столбце есть значение NULL, результат должен быть (Select Count (Distinct COLNAME) Из ТАБЛИЦЫ) + 1 .

Это будет повторяться для каждого столбца в каждой таблице в БД.Включает сотни таблиц, некоторые из которых содержат более 1 миллиона строк. Поскольку это нужно делать для каждого отдельного столбца, добавление индексов для каждого столбца - не лучший вариант.

Это будет сделано как часть сайта ASP.net, поэтому интеграция с логикой кода также возможна (то есть: это не обязательно должно выполняться как часть одного запроса, хотя, если это можно сделать с хорошей производительностью , тогда даже лучше).

Каков наиболее эффективный способ сделать это?


Обновить после тестирования

Я протестировал различные методы из ответов, представленных на хорошей репрезентативной таблице. В таблице 3,2 миллиона записей, десятки столбцов (некоторые с индексами, большинство без). Один столбец содержит 3,2 миллиона уникальных значений. Другие столбцы варьируются от всех Null (одно значение) до максимум 40K уникальных значений. Для каждого метода я провел четыре теста (с несколькими попытками для каждого, усредняя результаты): 20 столбцов за один раз, 5 столбцов за один раз, 1 столбец с множеством значений (3,2M) и 1 столбец с небольшим количеством значений ( 167).Вот результаты в порядке от самого быстрого к самому медленному

  1. Count / GroupBy ( Cheran )
  2. CountDistinct + SubQuery ( Ellis )
  3. density_rank ( Eriksson )
  4. Count + Max ( Andriy )

Результаты тестирования (в секундах):

   Method          20_Columns   5_Columns   1_Column (Large)   1_Column (Small)
1) Count/GroupBy      10.8          4.8            2.8               0.14       
2) CountDistinct      12.4          4.8            3                 0.7         
3) dense_rank        226           30              6                 4.33 
4) Count+Max          98.5         44             16                12.5        

Примечания:

  • Интересно достаточно, два метода, которые были самыми быстрыми (безусловно, с небольшой разницей между ними), были оба метода, которые отправляли отдельные запросы для каждого столбца (и в случае результата №2 запрос включал подзапрос, поэтому были на самом деле два запроса отправлены на столбец). Возможно, потому, что выигрыш, который может быть достигнут за счет ограничения количества сканирований таблиц, невелик по сравнению с падением производительности, полученным с точки зрения требований к памяти (просто предположение).
  • Хотя метод density_rank определенно является наиболее элегантным, кажется, что он плохо масштабируется (см. Результат для 20 столбцов, что является наихудшим из четырех методов), и даже в небольшом масштабе просто не может посоревноваться с показателем графа .

Спасибо за помощь и предложения!

10
задан Community 23 May 2017 в 12:00
поделиться