Операция Transact-Sql Count Distinct подсчитывает все ненулевые значения в столбце. Мне нужно посчитать количество различных значений на столбец в наборе таблиц, включая нулевые значения (поэтому, если в столбце есть нулевое значение, результат должен быть (Select Count(Distinct COLNAME) From TABLE) + 1
.
Это будет повторяться для каждого столбца в каждой таблице в БД. Включает в себя сотни таблиц, некоторые из которых имеют более 1 млн строк. Поскольку это необходимо делать для каждого отдельного столбца, добавление индексов для каждого столбца не является хорошим вариантом.
Это будет сделано как часть сайта ASP.net, так что интеграция с логикой кода также в порядке (то есть: это не нужно выполнять как часть одного запроса, хотя, если это можно сделать с хорошей производительностью тогда еще лучше).
Какой самый эффективный способ сделать это?
<ч />
Обновление после тестирования
Я проверил различные методы из ответов, приведенных в хорошей репрезентативной таблице. Таблица содержит 3,2 миллиона записей, десятки столбцов (несколько с индексами, большинство без). Один столбец имеет 3,2 миллиона уникальных значений. Другие столбцы варьируются от всех Null (одно значение) до максимум 40K уникальных значений. Для каждого метода я выполнил четыре теста (с несколькими попытками на каждом, усредняя результаты): 20 столбцов за один раз, 5 столбцов за один раз, 1 столбец с множеством значений (3.2M) и 1 столбец с небольшим количеством значений ( 167). Вот результаты, в порядке от самого быстрого до самого медленного
- Count / GroupBy ( Cheran )
- CountDistinct + SubQuery ( Ellis )
- density_rank ( Eriksson )
- Количество + Макс ( Андрей )
Результаты тестирования (в секундах):
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, запрос включал подзапрос Таким образом, на каждый столбец было отправлено два запроса. Возможно, потому что выигрыш, который был бы достигнут за счет ограничения количества сканирований таблиц, невелик по сравнению с ударом по производительности с точки зрения требований к памяти (только предположение).
- Хотя метод dens_rank, безусловно, самый элегантный, кажется, что он плохо масштабируется (см. Результат для 20 столбцов, что является худшим из четырех методов), и даже в небольшом масштабе просто не может конкурировать с производительностью
Count
.
Спасибо за помощь и предложения!