Pull to refresh
98
0
Send message
По поводу такого количества минусов, я немного удивлен. Неужели всем интересно приходить на собеседование и отвечать на вопросы с листочка? Это конвейер чистой воды… :)
Надеюсь у Вас не сложилось мнение, что я люблю «доминировать» на собеседовании. :) Это далеко не так… Ничего сложного я никогда не спрашивал. Лишь то что нужно для работы. И такие вот моменты что были в этом посте… я их не спрашивал, а рассказывал… потому что с людьми было приятно поделиться опытом. Точно также они и мне рассказывали вещи, которые я не знал.

Теперь по поводу простых вопросов… Многие даже не могут на такой вопрос ответить:

DECLARE @t TABLE (a INT)
INSERT INTO @t (a) VALUES (1), (2), (3), (NULL)

SELECT AVG(a), COUNT(*), COUNT(a)
FROM @t

Одного он вообще повергнул в шок… И мы вместе сидели и разбирались. Почему AVG вернет — 3, а не 1.5 и тд…
При выполнении разница будет только во времени компиляции запроса.

IF OBJECT_ID('dbo.test', 'U') IS NOT NULL
    DROP TABLE dbo.test
GO

;WITH E1(N) AS (
    SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL 
    SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL 
    SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1
)                                    
, E2(N) AS (SELECT 1 FROM E1 a, E1 b)
, E4(N) AS (SELECT 1 FROM E2 a, E2 b)
, E8(N) AS (SELECT 1 FROM E4 a, E4 b)

SELECT val = 1
INTO dbo.test
FROM E8

IF EXISTS(SELECT * FROM dbo.test)
    PRINT 1

IF EXISTS(
    SELECT *
    FROM sys.dm_db_partition_stats
    WHERE [object_id] = OBJECT_ID('dbo.test')
        AND row_count > 0
        AND index_id < 2
) PRINT 1

TRUNCATE TABLE dbo.test
--DELETE TOP(50) PERCENT FROM dbo.test

IF EXISTS(SELECT * FROM dbo.test)
    PRINT 1

IF EXISTS(
    SELECT *
    FROM sys.dm_db_partition_stats
    WHERE [object_id] = OBJECT_ID('dbo.test')
        AND row_count > 0
        AND index_id < 2
) PRINT 1

План будет одинаковый:



Estimated Number of Rows тоже будет идентичным в обоих случаях. А вот количество Actual Number of Rows будет различаться (когда данные есть в таблице и когда их нет, что вполне логично).

Никто не говорил, что нужно гоняться за точностью. Лично я всегда использую sys.partitions вместо COUNT(*) по таблице. Но знать о потенциальных проблемах с некорректными данными в системных представлениях нужно. Или хотя бы иметь представление куда копать в случае проблем подобного рода.
Между прочим и меня часто ловили на всякой ереси :) не всегда же можно все держать в голове на собеседовании. Люди же подсознательно всегда волнуются. А так начал с простого и диалог сам собой начинается.
Хороший вопрос. Если честно, то ответа я не жду. У меня свое видение процесса собеседования. Просто задвавать вопросы быстро наскучивает. Гораздо интереснее начать с простого и понятного вопроса и на основе него построить беседу. Многие из тех кого я побеседовал приходили проверить свой уровень, а не устраиваться на работу. Такие моменты быстро можно уловить и тогда остается просто поговорить о чем-то интересном. Опытом обменяться…
Фраза относилась к оператору Computed Scalar в целом, а не к усечению. Общепризнанные факт, что данный оператор по стоимости на плане практически всегда нулевой или близкий к нему. А по факту может существенно снижать производительность.
Такого плана комментарии мне по душе. Спасибо. Завтра утром выводы добавлю.
WHERE EXISTS(SELECT * FROM ...)

в такой конструкции тоже раньше советовали использовать константу. Даже Ицик Бен-Ган об этом в книжке своей писал :)
Приведите, пожалуйста, пример.

Разница между 1 и * была еще во времена SQL Server 2000. Точно могу сказать, что с 2005 планы генерируются одинаково. Если планы одинаковые, то и выполнение будет одинаковым (в рамках погрешности и при условии, что ресурсы сервера ничем другим в это время не нагружены). Единственное что может отличаться, время компиляции.
Оптимизатор для этих запросов генерирует идентичный план выполнения:

SELECT COUNT_BIG(*) FROM t1
SELECT COUNT_BIG(1) FROM t1

Если сравнить планы, то разница только в * и 1:



Table 't1'. Scan count 6, logical reads 114911, physical reads 0, ....
 SQL Server Execution Times:
   CPU time = 2673 ms,  elapsed time = 1787 ms.

Table 't1'. Scan count 6, logical reads 114911, physical reads 0, ....
 SQL Server Execution Times:
   CPU time = 2625 ms,  elapsed time = 1878 ms.
Добрые люди, если минусуете, то просьба говорить за что… а то получается «анонимных клуб народных мстителей» :)
Спасибо за комментарий. В целом с Вашей точкой зрения согласен.

Однако, нужно отметить — эту возможность я привел для примера. Доступна она только для Enterprise и раз уж ее добавили в эту редакцию, значит от нее иногда есть польза. Когда я нею последний раз пользовался на 2005 сервере, то она отрабатывала быстрее чем создание бекапа, а потом копирование его на шару. Далее никто не запрещает после выполнить RESTORE VERIFYONLY, чтобы проверить корректность созданного бекапа.

Буду очень благодарен, если Вы поделитесь с окружающими скриптами по переносу бекапа на шару.
Еще забыл добавить… При включении Transparent Data Encryption (позволяет шифровать файлы на диске), Instant File Initialization работать не будет.
Очень подробный ответ. Спасибо.

Теперь по поводу осторожности… Если есть возможность ускорить дисковые операции, то почему не воспользоваться? Вопросы безопасности стоят не во всех организациях. Некоторым подавай максимальную производительность. А бывают ситуации, когда сервер ушел в мир иной и нужно в кратчайшие сроки восстановить базу из бекапа на другом железе. Там применение Instant File Initialization может сократить простой организации и нервы окружающих.
Instant File Initialization я включал для всех серверов, на которых работал и за два года не увидел никаких проблем при ее использовании. Кто столкнулся с проблемами – напишите в комментариях. Буду очень благодарен.
Спасибо за комментарий. Забыл об этом упомянуть. Сжатие поддерживают:

2008 – только Enterprise и Developer
2008R2 / 2012 / 2014 – редакции Enterprise, Business Intelligence, Standard, Developer
Попробуйте заменить блок:

BEGIN TRY
    EXEC sys.sp_refreshsqlmodule @name = @obj_name
END TRY
BEGIN CATCH
    INSERT INTO #objects (obj_name, err_message, obj_type) 
    SELECT @obj_name, ERROR_MESSAGE(), @obj_type
END CATCH

на вот такой:

BEGIN TRY

	BEGIN TRANSACTION
		EXEC sys.sp_refreshsqlmodule @name = @obj_name, @namespace = N'OBJECT' 
	COMMIT TRANSACTION

END TRY
BEGIN CATCH
	INSERT INTO #objects (obj_id, obj_name, err_message, obj_type) 
	SELECT @obj_id, @obj_name, ERROR_MESSAGE(), @obj_type

	IF XACT_STATE() <> 0
		ROLLBACK TRANSACTION
END CATCH
Спасибо за комментарий. Я проверю в чем может быть проблема и обновлю пост.
Точно знаю, что невалидные объекты есть в Oracle и SQL Server, поскольку на уровне метаданных есть соответствующие признаки. Например, Oracle переводит объекты в состояние INVALID, если зависимый объект изменяется. Если следующая компиляция проходит успешно, то объект становится помечается как VALID.

Information

Rating
Does not participate
Registered
Activity