Pull to refresh
96
0
Send message
Большое спасибо за Ваш комментарий. Было очень интересно почитать и новые нюансы для себя узнать.
SELECT *
FROM (
	SELECT val = 1
	UNION ALL
	SELECT 2
	UNION ALL
	SELECT 3
) t

SELECT *
FROM (
	VALUES(1), (2), (3)
) t (val)


Первый пример работает на всех актуальных версиях. Второй только с 2008.

Нет. Это не временная таблица. Просто возможность задать константный набор строк.
Спасибо за ответ :)

В целом с Вами согласен. Но все же нужно знать возможности того инструмента которым работаешь.
Спасибо за комментарий. Вспомнил еще один хороший пример «как не надо делать»:

IF (SELECT COUNT(*) FROM ...) > 0
BEGIN
	...
END

Видел примеры такого кода для проверки есть в таблице записи.
К чему такая латентная агрессия...? Не пойму чем я Вас задел. «Такие как вы»… Это какие? :)

Теперь по существу. Ситуации номер раз. Приходит на работу джуниор, коим и я когда-то был. С него, что должен быть спрос много-чего знать? Нет. Только желание работать и развиваться.

Ситуация номер два. Приходит человек с «опытом» и просит соответствующий оклад. Мне про что с ним нужно говорить...? Про абстрактные основы институтской программы? Думаю, что нет. Нужно понять его уровень квалификации и готов ли он выполнять свою работу. А для этого нет необходимости пудрить серое вещество спрашивая про вещи, которые в повседневности не нужны. И тут мы возвращаемся к тому простому вопросу о котором было написано в самом начале.
Прощу прощение, видимо часть фразы затер случайно и не заметил.

с точки зрения точности, наиболее корректное число строк можно получить при Full Scan. Но в зависимости от уровня изоляции, хинтов и т.д. понятие «корректное» уйдет на второй план. Например, когда используется хинт NOLOCK — это приводит к грязные чтениям.

По этой причине, я всегда стараюсь смотреть в метаданных эту информацию.

Еще раз спасибо, что обратили внимание на ошибку в ответе.
До редактирования статьи заголовок был менее пафосных… Зато народ привлек. Много мнений услышал. Кое-что новое для себя узнал. Кстати, за Ваш пост спасибо… альтернативу для Zabbix недавно искал.
Предположим человек приходит на должность SQL Server Database Developer. В резюме 3 года опыта работы с БД под SQL Server. Если он не может ответить на такой вопрос… какие результаты вернет запрос… даже после получаса наводящих вопросов, то поневоле стоит задуматься…

SELECT COUNT(1), COUNT(*), COUNT(val), COUNT(DISTINCT val)
FROM (
	VALUES (1), (1), (2), (NULL), (NULL)
) t (val)

А по поводу этого примера, так это конструкция языка, которой пользуются очень часто. Нужно понимать возможности того языка, который используешь.
а) если метаданные для таблицы содержат
б) разницы, как уже говорил ранее — нет. погрешность лишь во времени компиляции каждого конкретного запроса

Да, еще я часто встречал такой способ «SELECT TOP 1 1 FROM Table», как насчет него?

SELECT TOP 1 1
FROM Sales.SalesOrderDetail

SELECT 1
WHERE EXISTS(
	SELECT *
	FROM Sales.SalesOrderDetail
)

SQL Server считает что с TOP(1) будет немного быстрее:



Время выполнения в рамках погрешности:

Table 'SalesOrderDetail'. Scan count 1, logical reads 2, physical reads 0, ...
 SQL Server Execution Times:
   CPU time = 5 ms,  elapsed time = 5 ms.

Table 'SalesOrderDetail'. Scan count 1, logical reads 2, physical reads 0, ...
 SQL Server Execution Times:
   CPU time = 4 ms,  elapsed time = 6 ms.

План сравнивал не в SSMS, а в dbForge, чтобы Вы увидели разницу в оценке батчей.
У меня есть подборка простеньких вопросов, которые я люблю задавать при собеседовании. Например, как посчитать общее число записей к таблице? Вроде бы ничего сложного, но если копнуть глубже, то можно много интересных нюансов рассказать собеседнику.

Повторюсь… Я такие тонкости не спрашиваю. Ключевое слово рассказать… Многие на работу приходят не только за деньгами, а но из за новыми знаниями. Если показать человеку, чему его могут здесь научить, то больше вероятность его положительного ответа на предложение о работе.
Предположим, что в таблице миллион записей. Мы пытаемся их удалить. Значение количества строк в метаданных не будет изменяться, до тех пор пока в журнале не зафиксируются изменения командой DELETE. Если мы пытаемся очистить таблицу с помощью TRUNCATE, то страницы на которых хранятся таблицы будут помечены как свободные для записи, будет сброшен счетчик числа строк в метаданных…

Надеюсь я смог ответить на Ваш вопрос.
Только для SQL Server, поскольку с другими DBMS работал мало.
У нас сейчас начинается холивар… Мне что рассказать как работают операции DELETE и TRUNCATE? Про минимальное протоколирование и т.д… Приведите, пожалуйста, пример и расскажите людям что Вас интересует. Я честно, не понимаю сути того, что Вы от меня хотите услышать.
Я подумаю по поводу репро для на выходных. К слову будет сказано… SQL Server как правило недооценивает Computed Scalar, и в тоже время переоценивает XML операторы…
«использование метаданных как было показано выше не даст особых преимуществ» эта фраза была в контексте чего приведена?.. Когда нужно проверить есть ли записи в таблице — разницы нет, какой подход применять. Если надо узнать количество строк в таблице, то быстрее всего это можно получить из метаданных. Это данность бытия…

Разница между TRUNCATE и DELETE есть, но вопрос был не о них ранее. Или все же о них?
Опечатался… Сорри :)

Оптимизатор раскладывает AVG(a) на операции SUM(a) / COUNT(a)
COUNT(a) подсчитывает значения, которые не NULL. Поэтому и получается результат, который привел BelAnt.

и тут еще был нюанс. Раз столбец INT, то и результат операции AVG будет целочисленным. Например, в такой ситуации среднее значение вернется не совсем такое как ожидается:

SELECT AVG(a)
FROM (VALUES(1), (2)) t(a)

Т.е. мы ожидаем 1.5, а будет 1… :)
Почему AVG вернет — 3


опечатался, когда отвечал. BelAnt спасибо, что обратили внимание.
Этот отчет не настолько информативный, чтобы мне было ним удобно пользоваться. Я вот таким запросом смотрю то что мне нужно:

SELECT 
      o.[object_id]
    , s.name + '.' + o.name
    , o.[type]
    , i.total_rows
    , total_space = CAST(i.total_pages * 8. / 1024 AS DECIMAL(18,2))
    , used_space = CAST(i.used_pages * 8. / 1024 AS DECIMAL(18,2))
    , unused_space = CAST((i.total_pages - i.used_pages) * 8. / 1024 AS DECIMAL(18,2))
    , index_space = CAST(i.inx_pages * 8. / 1024 AS DECIMAL(18,2))
    , data_space = CAST(data_pages * 8. / 1024 AS DECIMAL(18,2))
    , is_heap
    , i.[partitions]
    , i.[indexes]
FROM sys.objects o
JOIN sys.schemas s ON o.[schema_id] = s.[schema_id]
JOIN (
    SELECT
          i.[object_id]
        , is_heap = MAX(CASE WHEN i.index_id = 0 THEN 1 ELSE 0 END)
        , total_pages = SUM(a.total_pages)
        , used_pages = SUM(a.used_pages)
        , inx_pages = SUM(a.used_pages - CASE WHEN a.[type] !=1 THEN a.used_pages WHEN p.index_id IN(0,1) THEN a.data_pages ELSE 0 END) 
        , data_pages = SUM(CASE WHEN a.[type] != 1 THEN a.used_pages WHEN p.index_id IN (0,1) THEN a.data_pages END)
        , total_rows = SUM(CASE WHEN i.index_id IN (0, 1) AND a.[type] = 1 THEN p.[rows] END)
        , [partitions] = COUNT(DISTINCT p.partition_number)
        , [indexes] = COUNT(DISTINCT p.index_id)
    FROM sys.indexes i
    JOIN sys.partitions p ON i.[object_id] = p.[object_id] AND i.index_id = p.index_id
    JOIN sys.allocation_units a ON p.[partition_id] = a.container_id
    WHERE i.is_disabled = 0
        AND i.is_hypothetical = 0
    GROUP BY i.[object_id]
) i ON o.[object_id] = i.[object_id]
WHERE o.[type] IN ('V', 'U')
    AND o.is_ms_shipped = 0
ORDER BY i.total_pages DESC
Выводы добавил. Спасибо за комментарий.
Спасибо за комментарий. Позвольте еще раз обратить внимание на то, что мнение это касается преобразования типов в целом. Любые Compute Scalar операторы требуют ресурсов при их выполнении. Одни больше… другие меньше.

Information

Rating
Does not participate
Registered
Activity