Arquivo
Lista de 275 dicas de performance… até agora…
A lista vai longe… Pelo que percebi, vai ser sem fim… Já temos 175 dicas gravadas e disponíveis em https://cursos.powertuning.com.br/
— Parte 1
1 – Cuidado com “missing index”
2 – Cuidados com NULL
3 – Estatísticas – atualizando com valores falsos
4 – Estatísticas – colunas ascendentes
5 – Estatísticas – date correlation optimization
6 – Estatísticas – desatualizadas
7 – Estatísticas – faltando
8 – Estatísticas – gap
9 – Estatísticas – impacto em operaçoes de rebuild
10 – Estatísticas – múltiplas colunas
11 – Estressando uma consulta
12 – Indexando colunas calculadas
13 – Intersecçao de índices
14 – Like ‘%%’ – Fultext search
15 – Like Fultext search – Coringa no final + reverse
16 – Like ‘%%’ – SQL Collate
17 – Like ‘%%’ – Fragmentos de string
18 – Ordenaçao – disco HDD, performance do tempdb
19 – Ordenaçao – disco HDD, múltiplos arquivos do tempdb
20 – Ordenaçao – disco SSD, performance do tempdb
21 – Ordenaçao – disco SSD, múltiplos arquivos do tempdb
22 – Order by é necessário
23 – Pensando em sets, um exemplo
24 – Removendo LOB da página de dados
25 – Removendo lookups – Include
— Parte 2
26 – Otimizando inserçoes – Parallel insert, SQL2014+
27 – Otimizando inserçoes – Operaçoes minimamente logadas
28 – Otimizando inserçoes – SSIS + Balaced Data Distributor
29 – Otimizando inserçoes – Batch único ou vários inserts
30 – Reescrita de T-SQL – Missing spool
31 – Reescrita de T-SQL – Subquery ou CrossApply
32 – Reescrita de T-SQL – LINQ vs TOP
33 – Reescrita de T-SQL – Group by()
34 – Row goal – Forceseek
35 – Row goal – TOP N, TOP 100
36 – Evitando HP – functions schemabinding
37 – Evitando HP – evitando spool
38 – Wide e narrow plans
39 – SET ou SELECT
40 – Variáveis locais ou parâmetros de entrada
41 – Variáveis do mesmo tipo da coluna
42 – Será que seek é sempre melhor que scan
43 – Expurgo de forma eficiente
44 – Utilizando clausula output
45 – Residual predicates
46 – Prefira um “between” a “IN”
47 – Forçando paralelismo
48 – Seek – quem filtra, index seek ou predicate
49 – Otimizando algoritmo de merge join
50 – Debug tupiniquim com RAISERROR WITH NOWAIT
— Parte 3
51 – Distinct ou group by
52 – TOP 1 ORDER BY DESC ou MAX
53 – Not In ou Not Exists
54 – Subqueries ou CrossOuter apply
55 – Union all VS Union
56 – Count(1) ou Count (asterisco)
57 – Ordem da escrita do join, importa
58 – Escrevendo códigos dinâmicos com eficiência
59 – Reescrevendo OUTER JOINS complexos
60 – CTE para evitar múltiplo acesso a functions
61 – Importância do cache plan
62 – Filtros dinâmicos, utilizando “parameter embedding optimization”
63 – “Parameter embedding optimization” – limitaçao com variável
64 – Evitando recompilaçoes
65 – Minimizando tempo de compilaçao – Merge interval bug
66 – Desnormalizando para obter performance
67 – Utilizando tabela numérica auxiliar
68 – Retornando maior valor de várias colunas
69 – Tabela de sequencia + identity vs sequence
70 – WITH ENCRYPTION nao funciona… nem perca tempo
71 – Processamento em paralelo no SQL (multi threads com CLR)
72 – Scan – Removendo fragmentaçao
73 – Scan – Ajustando fillfactor
74 – Scan – Aplicando compressao de dados
75 – Scan – Scan direction e paralelismo
— Parte 4
76 – Views indexadas
77 – Indice cluster – único
78 – Indice cluster – estático
79 – Indice cluster – sequencial
80 – Indice cluster – pequeno
81 – Particionamento – eliminaçao de partiçao
82 – Indices únicos com vários valores NULL
83 – Cuidados com nolock – leituras sujas
84 – Cuidados com nolock – lendo mesma linha mais de uma vez
85 – Cuidados com nolock – pulando linhas
86 – Cuidados com nolock – mascarando erros de corrupçao
87 – Cuidado, case + subqueries
88 – Otimizando COUNT (DISTINCT…)
89 – Otimizando cursores
90 – Utilizando SET STATISTICS IO, cuidado com funçoes
91 – TOP com empate
92 – Otimizando queries utilizando linked server
93 – Cuidados com nolock – movimentaçao dos dados
94 – Validando se a tabela está vazia… o que usar
95 – Stream aggregate e compute scalar – Otimizando agregaçao
96 – Conversoes implícitas
97 – Filtros – Iniciando com ‘Z’
98 – Filtros – Removendo hora da data
99 – Minimizando compilaçao de queries ad-hoc com plan guides
100 – Convertendo scalar function em inline function
— Parte 5
101 – Criando índices hipotéticos
102 – Indices filtrados
103 – Bushy plans
104 – Hash e order group hints
105 – Planos de execuçao com “time out” na criaçao, TF8780
106 – Planos bons o suficiente
107 – Agregaçoes de vetor e agregaçoes escalares
108 – Parameter sniffing problem
109 – Aplicaçao, parametrizando corretamente – evitando cachebloat
110 – Split de string
111 – Gerando uma string delimitada
112 – Contando a quantidade de caracteres em uma string
113 – Identificando linhas duplicadas
114 – Identificando ilhas
115 – Identificando gaps
116 – Lendo valor da linha anterior
117 – Lendo valor da linha posterior
118 – Identificando valores faltando
119 – Retornando “running aggregations”
120 – Transformando linhas em colunas dinamicamente
121 – Ignorando linhas duplicadas
122 – Qual impacto de sp
123 – Qual impacto de set no count
124 – Escondendo códigos do DBA
125 – Ignorando todos os inserts
— Parte 6
126 – Retornando a quantidade de linhas de uma tabela
127 – Simulando ambiente de produçao em desenvolvimento
128 – Cuidados com performance das funçoes de janela
129 – Check constraints e sua relaçao com performance
130 – Foreign keys e sua relaçao com performance
131 – Evitando contençao de alocaçao de objetos no tempdb
132 – Utilizando variáveis do tipo tabela com eficiência
133 – Escrevendo consultas recursivas
134 – XML – Indices seletivos
135 – Paginaçao, como fazer
136 – Indices únicos e seus benefícios
137 – Force order
138 – Ajustando query wait
139 – Java + parametros unicode
140 – Obtendo mais performance com prefetch
141 – Problemas de bloqueios causados por prefetch
142 – Cuidados com SQL Injection
143 – Cuidados com ISNUMERIC
144 – IF condiçao AND condiçao ou IF condiçao IF condiçao
145 – Erro com ISNULL(ColunaQueNaoAceitaNULL) + colunas calculadas
146 – Problemas com “auto create_update statistics”
147 – Query com OPTION(MAXDOP 1) gerando wait em CXPACKET
148 – Minimizando bloqueios com indexaçao
149 – Lock escalation
150 – Melhorando performance de MIN e MAX em tabelas particionadas
— Parte 7
151 – Reescrita de T-SQL – Quebrando query utilizando tabelas temporárias
152 – Reescrita de T-SQL – Trocando JOIN + OR por CROSS APPLY e UNION
153 – Reescrita de T-SQL – Otimizando DISTINCT COUNT
154 – Reescrita de T-SQL – SARG vs NONSARG e filtros dinâmicos
155 – Reescrita de T-SQL – Otimizando query com ORDER BY e NULLS LAST
156 – Reescrita de T-SQL – Evitando sort em query com OVER(Col ORDER BY DESC)
157 – Reescrita de T-SQL – Cursor melhor que set-based
158 – Eita, eu nao sabia que da pra fazer isso (TRANSLATE)
159 – Eita, eu nao sabia que da pra fazer isso (TRIM)
160 – Eita, eu nao sabia que da pra fazer isso (CONCAT_WS)
161 – Eita, eu nao sabia que da pra fazer isso (DECLARE @c CURSOR)
162 – Eita, eu nao sabia que da pra fazer isso (AS Tab(ColName))
163 – Eita, eu nao sabia que da pra fazer isso (DROP TABLE Tab1, Tab2)
164 – Eita, eu nao sabia que da pra fazer isso (TRUNCATE com WHERE)
165 – Utilizando otimizaçao de insert mais rápido no SQL2014+ e tempdb
166 – Testando hyper-threading
167 – CachePlan – Simple – AutoParam
168 – CachePlan – Cuidados com parameterizaçao na App e TF144
169 – CachePlan – Optimize for adhoc workloads.json
169 – CachePlan – Optimize for adhoc workloads
170 – CachePlan – sp_prepare vs direct exec
171 – CachePlan – Textos iguais, hash tem que bater
172 – CachePlan – Plan Reuse-affecting set options
173 – Apagando um índice para deixar uma consulta mais rápida
174 – Comprimindo VARCHAR(MAX) com ColumnStore
175 – Deu ruim quando liguei read commited snapshot isolation level
— Ainda não publicado:
— Parte 8 (edição TraceFlags)
176 – Utilizando traceflag 174
177 – Utilizando traceflag 610
178 – Utilizando traceflag 715
179 – Utilizando traceflag 1117
180 – Utilizando traceflag 2335
181 – Utilizando traceflag 2371
182 – Utilizando traceflag 2453
183 – Utilizando traceflag 2505
184 – Utilizando traceflag 2548
185 – Utilizando traceflag 3042
186 – Utilizando traceflag 3226
187 – Utilizando traceflag 7412
188 – Utilizando traceflag 7470
189 – Utilizando traceflag 7471
190 – Utilizando traceflag 8602
191 – Utilizando traceflag 8666
192 – Utilizando traceflag 8677
193 – Utilizando traceflag 8690
194 – Utilizando traceflag 8722
195 – Utilizando traceflag 8755
196 – Utilizando traceflag 8757
197 – Utilizando traceflag 9130
198 – Utilizando traceflag 9389
199 – Utilizando traceflag 9481
200 – Utilizando traceflag 9495
— Parte 9 (edição SQL2019)
201 – Batch mode over row store
202 – Batch mode over row store, Internals
203 – Row mode memory grant feedback
204 – Table variable deferred compilation – Demo 1
205 – Table variable deferred compilation – Demo 2
206 – Scalar UDF inlining – 1
207 – Scalar UDF inlining – 2 (bad case)
208 – Accelerated database recovery – Demo 1
209 – Accelerated database recovery – Demo 2
210 – Lightweight query plan ligado por padrao
211 – sys.dm_exec_query_plan_stats
212 – Compression estimates para column store
213 – Novo wait (WAIT_ON_SYNC_STATISTICS_REFRESH)
214 – Suporte a persisted memory
215 – Emulando PMEM (persisted memory) no Linux
216 – APPROX_COUNT_DISTINCT
217 – Novos hints – sys.dm_exec_valid_use_hints
218 – sys.dm_db_page_info
219 – Tempdb in-memory system objects
220 – Transparent Data Encryption (TDE) scan – suspend and resume
221 – Reduçao de recompilaçao para workloads utilizando tabelas temporárias
222 – Suporte a UTF-8
223 – Resume e Pause para criaçao de índices online
224 – Criaçao de índices columnstore online
225 – Improved indirect checkpoint scalability
— Parte 10
226 – Permissao LinkedServer SQL2008R2
227 – Filtros LinkedServer Local VS Remote
228 – LinkedServer vs sp_prepexec e sp_execute
229 – LinkedServer INNER REMOTE JOIN
230 – LinkedServer collation compatible
231 – LinkedServer vs halloween protection
232 – LinkedServer vs MARS
233 – View indexada vs Blocks e DeadLocks
234 – Nível de isolamento vs Entity Framework
235 – Nível de isolamento padrao, lock em select
236 – Lock extra de query rodando em paralelo
237 – Lock extra de query acessando LOB
238 – Lock extra de query com halloween protection
239 – Impacto de conexoes com MARS habilitado
240 – Problema de performance com funçao FORMAT
241 – Memory leak no JDBC
242 – Ajustando cost threshold for parallelism
243 – Troubleshoot com windows performance toolkit
244 – Otimizando velocidade dos backups
245 – A significant part of sql server process memory has been paged out…
246 – BP data cache – free_space_in_bytes e fragmentaçao
247 – BP data cache – utilizando compressao de dados
248 – BP data cache – entendendo page disfavoring
249 – Obtendo informaçoes uteis do default trace
250 – Analisando deadlock envolvendo apenas uma tabela
— Parte 11
251 – Operador do plano de execução – IndexSeek
252 – Operador do plano de execução – Table Spool (Lazzy Spool)
253 – Operador do plano de execução – Table Spool (Eager Spool)
254 – Operador do plano de execução – Index Spool
255 – Operador do plano de execução – KeyLookup apenas pra fazer predicate
256 – Operador do plano de execução – RowCount Spool
257 – Operador do plano de execução – Merge interval
258 – Operador do plano de execução – Split, Sort e Collapse
259 – Operador do plano de execução – Loop join
260 – Operador do plano de execução – Merge join
261 – Operador do plano de execução – Hash join
262 – Operador do plano de execução – Hash join vs residual predicate
263 – Operador do plano de execução – Adaptive join
264 – Foldable expressions
265 – NonUpdating updates
266 – Group hints
267 – DBCC OPTIMIZER_WHATIF
268 – Ligando e desligando optimizer query rules
269 – xEvent – inaccurate_cardinality_estimate
270 – QO Bug, Expressions In Queries
271 – QO Bug, IS NOT NULL
272 – QO Bug, Produto Cartesiano
273 – QO Bug, Segment Operator
274 – QO Bug, Filter VS Aggregation
275 – QO Bug, MERGE
Video, disk I/O no SQL Server
Quando eu gravei esse vídeo, minha cabeça tava tão maluca e com tanta informação… Eu havia pesquisado e estudado tanto nos últimos meses que hoje consigo ver no vídeo o quão maluco eu estava rs… Esse treinamento é meu orgulho, se você ainda não viu esse vídeo e usa SQL Server, assista…
Abs.
Fabiano
Scripts, Live DBA Solidário, DBA Brasil
De volta com um treinamento presencial em SP
Fala galera, confesso que eu estava ansioso pra escrever esse post.
Indo direto ao ponto, esse ano voltarei a ministrar um treinamento presencial, e vai ser o mais maluco/completo que já ministrei.
A ementa provavelmente será a seguinte:
1 – Internals – SQLOS, Waits e CPU
2 – Internals – Memória Parte 1
3 – Internals – Memória Parte 2
4 – Internals – Disk I/O
5 – Internals – Latch, Spinlock e TempDB
6 – Internals – Índices, Otimizador de consultas e estatísticas
7 – Internals – Gerenciamento de concorrência e performance tuning parte 1
8 – Internals – Segurança e performance tuning parte 2 + graduação dos sobreviventes e/ou enlouquecidos.
Local: Treinamento presencial em São Paulo-SP.
Carga horária: 64 horas. (praticamente uma faculdade)Quando: Datas e horários a definir.
Horário provavelmente será no integral aos sábados ou no período noturno, ainda vou decidir.
Datas provavelmente em Julho e Agosto.
Valor: R$ 5.000,00 (cinco mil reais) (vou pensar numa forma de parcelar esse valor pra facilitar)
Obviamente estou contanto que teremos voltado ao “quase normal’ com a vacinação e que a pandemia esteja mais controlada.
As vagas serão limitadas portanto se você quer reservar sua vaga, por favor me envie um e-mail ou me chama no Zap o quanto antes pra gente conversar.
Abs.
Fabiano
Reorganize e o impacto gerado por bloqueios
Vamos lá, comecei a escrever um texto pra falar sobre bloqueios e vi que ele estava ficando muito grande, então eu assumi que ele ia ficar grande e aproveitei pra fazer um texto mais completo.
Pra entender um pouco mais sobre como funcionam os bloqueios e qual o impacto de um Reorganize, vamos começar com um simples exemplo e detalhar o que o SQL está fazendo.
Preparando o ambiente
Criando uma tabela pra usar nos testes.
USE Northwind
GO
— Preparar ambiente…
— 2 segundos para rodar
IF OBJECT_ID(‘OrdersBig’) IS NOT NULL
DROP TABLE OrdersBig
GO
SELECT TOP 1000000
IDENTITY(Int, 1,1) AS OrderID,
ABS(CheckSUM(NEWID()) / 10000000) AS CustomerID,
CONVERT(Date, GETDATE() – (CheckSUM(NEWID()) / 10000000)) AS OrderDate,
ISNULL(ABS(CONVERT(Numeric(18,2), (CheckSUM(NEWID()) / 1000000.5))),0) AS Value,
CONVERT(VARCHAR(250), NEWID()) + CONVERT(VARCHAR(250), NEWID()) + CONVERT(VARCHAR(250), NEWID()) AS ColNewID
INTO OrdersBig
FROM master.dbo.sysobjects A
CROSS JOIN master.dbo.sysobjects B CROSS JOIN master.dbo.sysobjects C CROSS JOIN master.dbo.sysobjects D
GO
ALTER TABLE OrdersBig ADD CONSTRAINT xpk_OrdersBig PRIMARY KEY(OrderID)
GO
Testes de um select simples utilizando com nível de isolamento padrão (READ COMMITTED)
Agora, suponhamos que eu rode o seguinte comando:
SELECT OrderID FROM Northwind.dbo.OrdersBig WHERE OrderID <= 3
Vou usar o sqlcmd pra rodar o select, o comando fica assim:
sqlcmd -S razerfabiano\sql2019 -U Login1 -P @bc12345 -Q “SELECT OrderID FROM Northwind.dbo.OrdersBig WHERE OrderID <= 3”
Internamente os bloqueios gerados ficam assim:
- Inicia uma transação implícita pro o comando, ou seja, todos os bloqueios serão controlados no escopo dessa transação. Pra esse caso, vamos considerar que TransactionID é 18935
- Adquire um S lock no banco Northwind
- Adquire um IS lock no objeto OrdersBig
- Adquire um IS lock no arquivo/página (1:85896)
- Adquire um S lock na linha (KEY) com o OrderID = 1, %%lockres%% = (8194443284a0)
- Libera o S lock na linha (KEY) com o OrderID = 1
- Adquire um S lock na linha (KEY) com o OrderID = 2, %%lockres%% = (61a06abd401c)
- Libera o S lock na linha (KEY) com o OrderID = 2
- Adquire um S lock na linha (KEY) com o OrderID = 3, %%lockres%% = (98ec012aa510)
- Libera o S lock na linha (KEY) com o OrderID = 3
- Libera o IS lock no arquivo/página (1:85896)
- Libera o IS lock no objeto OrdersBig
- Libera o S lock no banco Northwind
É possível ver essa sequência de eventos acontecendo utilizando o profiler para capturar os eventos de lock.
Algumas informações importantes em relação aos eventos:
- Um S lock é utilizado na linha pra garantir que enquanto a linha está sendo lida ninguém pode modifica-la. Ou seja, se enquanto o SQL estiver lendo a linha alguma sessão tentar fazer uma modificação nessa linha, ela ficará bloqueada.
- Repare que utilizando o nível de isolamento padrão (READ COMMITED), assim que uma linha é lida, o bloqueio é liberado, ou seja, o tempo que um LOCK de leitura é mantido na linha tende a ser muito rápido.
-
Intent lock é um conceito importante e que você precisa conhecer. Se quiserem falar mais sobre isso me avisa que eu preparo algo.
Testes do select com READUNCOMMITTED/NOLOCK
Se eu rodar a mesma query, porém utilizando o hint READUNCOMMITTED ou NOLOCK eu evito que uma sessão tentando alterar a linha fique bloqueada, porém corro o risco de ler dados sujos e etc (todos os outros problemas que já falei sobre NOLOCK, ver treinamento de dicas).
Só pra deixar a sequencia de eventos, a query com NOLOCK fica assim:
Como podemos ver no print do profiler, temos apenas um S lock no banco e um Sch-S lock na tabela pra evitar que a estrutura dela seja modificada enquanto a leitura está ocorrendo. Ou seja, uma query com NOLOCK pode gerar bloqueios de comandos DDL.
Testes do select com REPEATABLE/SERIALIZABLE READ
Com REPEATABLE/SERIALIZABLE READ o SQL precisa garantir que a leitura de uma linha terá o mesmo valor até o termino da query, ou seja, o lock na linha só será liberado quando todas as linhas forem lidas, diferente do comportamento em READ COMMITTED que libera o lock assim que a linhas é lida.
Consideração importante em relação aos níveis de isolamento mais pessimistas como REPEATABLE READ e SERIALIZABLE:
- Infelizmente, é muito comum os desenvolvedores utilizarem o nível de isolamento equivocado, ou seja, uma conexão que deveria utilizar um READ COMMITTED é aberta com SERIALIZABLE e isso passa a gerar uma série de locks (que podem gerar um lock escalation pra tabela) totalmente desnecessários e mais demorados, gerando bloqueios.
Exemplo de problema com Entity Framework
Criei uma aplicaçãozinha tosca que usa EF pra ler a tabela OrdersBig, a tela ficou assim:
O botão “button2” faz o seguinte:
private void button2_Click(object sender, EventArgs e)
{
using (System.Transactions.TransactionScope scope = new System.Transactions.TransactionScope(TransactionScopeOption.RequiresNew))
{
var v1 = new NorthwindEntities();
// Te dou um prêmio se você adivinhar qual é o IsolationLevel default…
// MessageBox.Show(Transaction.Current.IsolationLevel.ToString());
dataGridView1.DataSource = v1.OrdersBigs.Take(20000).ToList();
scope.Complete();
v1.Database.Connection.Close();
}
}
Estou usando tudo default e nada complexo, só iniciando uma transação e lendo as primeiras 20 mil linhas da tabela OrdersBig. Adivinha qual o nível de isolamento será utilizado?
Vamos ver o que o SQL nos diz em relação a essa sessão aberta pelo EF.
SELECT session_id, login_time, host_name, program_name, open_transaction_count,
CASE transaction_isolation_level
WHEN 0 THEN ‘Unspecified’
WHEN 1 THEN ‘Read Uncommitted’
WHEN 2 THEN ‘Read Committed’
WHEN 3 THEN ‘Repeatable Read’
WHEN 4 THEN ‘Serializable’
WHEN 5 THEN ‘Snapshot’
END AS [Transaction Isolation Level]
FROM sys.dm_exec_sessions
WHERE program_name LIKE ‘Entity%’
GO
Pois é, como eu disse, é preciso cuidado por parte dos desenvolvedores e atenção no monitoramento dos DBAs.
Olha o que esse select gerou de locks.
Além dos locks nas linhas até a query terminar, um lock escalation, tenso.
Testes com comando gerando modificações na tabela
Vamos supor o seguinte update pra atualizar 3 linhas da tabela OrdersBig:
UPDATE OrdersBig SET ColNewID =
‘Fabiano’
WHERE OrderID <= 3
Vou usar o sqlcmd pra rodar o select, o comando fica assim:
sqlcmd -S razerfabiano\sql2019 -U Login1 -P @bc12345 -Q “UPDATE Northwind.dbo.OrdersBig SET ColNewID = ‘Fabiano’ WHERE OrderID <= 3”
Internamente os bloqueios gerados ficam assim:
- Inicia uma transação implícita pro o comando, ou seja, todos os bloqueios serão controlados no escopo dessa transação. Pra esse caso, vamos considerar que TransactionID é 566400
- Adquire um S lock no banco Northwind
- Adquire um IX lock no objeto OrdersBig
- Adquire um IX lock no arquivo/página (1:85896)
- Adquire um X lock na linha (KEY) com o OrderID = 1, %%lockres%% = (8194443284a0)
- Adquire um X lock na linha (KEY) com o OrderID = 2, %%lockres%% = (61a06abd401c)
- Adquire um X lock na linha (KEY) com o OrderID = 3, %%lockres%% = (98ec012aa510)
- Libera o X lock na linha (KEY) com o OrderID = 1
- Libera o X lock na linha (KEY) com o OrderID = 2
- Libera o X lock na linha (KEY) com o OrderID = 3
- Libera o IX lock no arquivo/página (1:85896)
- Libera o IX lock no objeto OrdersBig
- Libera o S lock no banco Northwind
Novamente, conseguimos ver essa sequência de eventos acontecendo no profiler.
Até aqui, não temos novidades, o SQL pega um X lock em cada linha modificada e só libera quando todas as linhas forem modificadas, e tudo isso ocorre dentro do contexto de uma transação.
Mas e como ficam os bloqueios das leituras e as modificações geradas por um Reorganize?
Locks gerados por um reorganize
Bom, diz a lenda que um reorganize é lindo, é online e pode ser parado a qualquer momento sem crise.
Utilizando palavras da MS
“Reorganizing an index uses minimal system resources and is an online operation. This means long-term blocking table locks are not held and queries or updates to the underlying table can continue during the ALTER INDEX REORGANIZE transaction.”.
O truque pra que o reorganize não gere bloqueios é que ele não roda no contexto de uma única transação. (a não ser que você use uma transação explicita, ver https://github.com/MicrosoftDocs/sql-docs/pull/4011 do Mr. Rodrigo)
Vejamos isso na prática.
Dessa vez, pra monitorar os bloqueios gerados, além do profiler, vou usar também a “sp_whoisactive @get_locks = 1”.
Considerando então um:
ALTER
INDEX
ALL
ON Northwind.dbo.OrdersBig REORGANIZE
Enquanto o reorganize estava rodando, chamei a “sp_whoisactive @get_locks = 1” e o xml da coluna locks é o seguinte:
E no profiler temos o seguinte (estou exibindo apenas os dados relevantes).
SQL começa fazendo bloqueios internos, repare que o TransactionID é o 4670676.
Depois já podemos ver que ele cria várias pequenas transações, pra evitar longos bloqueios. Repare no TransactionID mudando.
Por fim, antes de terminar ele libera os bloqueios inicias do TransactionID 4670676.
Alguns comentários em relação a isso.
Aaaa, Fabiano, mas ele pegou um IX na tabela, isso ae não pode gerar problema? Vamos considerar os cenários que vimos nesse artigo.
Vamos pegar a tabela de compatibilidade de locks do help pra nos ajudar.
Existing granted mode |
|||||
Requested mode |
IS – Tabela |
S |
U |
IX – Tabela |
X – Página |
Intent shared (IS) |
Yes |
Yes |
Yes |
Yes |
No |
Shared (S) |
Yes |
Yes |
Yes |
No |
No |
Update (U) |
Yes |
Yes |
No |
No |
No |
Intent exclusive (IX) |
Yes |
No |
No |
Yes |
No |
Exclusive (X) |
No |
No |
No |
No |
No |
Eu realcei em vermelho os locks que o reorganize vai gerar, são eles: IS + IX na tabela e um X na página. Considerando esses locks operações ficariam bloqueadas?
“Select simples” – Primeiro exemplo que vimos nesse artigo.
Conforme vimos, um select simples gerou um IS na tabela, IS na página e alguns S nas linhas lidas. Olhando na tabela, podemos ver que quando o select tentar fazer um IS na página que já tem um X (já obtido pelo reorganize), ele vai ficar bloqueado. Portanto, sim o reorganize pode gerar bloqueios, podem na minha opinião eles serão extremamente rápidos, pois, lembre-se, o reorganize vai liberar o lock X na página assim que terminar a pequena transação que ele criou.
“Select com nolock”
O select com nolock não gerou locks na tabela, página ou linha, apenas um schema lock. Portanto o reorganize não causaria bloqueio.
“Select com serializable gerando lock escalation”
A demo com o aplicativo .net consultando o banco via EF gera os seguintes locks: IS na tabela, IS na página e um S nas linhas sendo lidas, também após atingir o threshold ( +- 5 mil locks) necessário pra disparar o lock escalation, o SQL “promoveu” o IS na tabela já obtido pra S.
Nesse cenário, a sessão ficará bloqueada quando tentar fazer IS na página que já tem um X (já obtido pelo reorganize), porém conforme eu já mencionei, esse bloqueio será muito rápido. Mas, o que vai acontecer quando o lock escalation ocorrer e ele tentar fazer um S na tabela? De acordo com a tabela de compatibilidades, um S na tabela
não é compatível com o IX na tabela já obtido pelo reorganize, sendo assim, o escalation não vai acontecer e o SQL vai continuar fazendo os locks nas linhas, uma nova tentativa de promover o IS pra S (lock escalation) será efetuada a cada 1250 novos locks obtidos. No nosso caso, ele não vai conseguir fazer o escalation nunca, pois o IX na tabela só será liberado quando o reorganize terminar.
Conclusão
Eu queria fazer outros testes, e ver outros cenários, mas já estou cansado e deu por hoje.
Novos Cursos E Promo De BlackFriday
Fala galera, tudo certo?
Passando pra falar um pouco sobre os meus treinamentos disponíveis na PowerTuning.
Eu sempre hesitei em fazer treinamentos no formato online, principalmente os de conteúdo avançado. é muito difícil entregar a mesma qualidade da experiência de um treinamento presencial no formato online, muito difícil, é um desafio enorme pra quem vai gravar o treinamento. Eu sempre gostei muito dos bate papos e discussões que tínhamos nos treinamentos presenciais que eu ministrava, e isso é quase totalmente perdido no online.
Bom, de qualquer forma, quando eu decidi que precisava rever minhas prioridades eu resolvi gravar alguns treinamentos e confesso que agora, vendo o resultado dos treinamentos e o feedback dos alunos que tenho recebido, devo dizer que estou extremamente feliz e satisfeito (não, satisfeito jamais, sempre dá pra melhorar) com os cursos. É muito gratificante ver a quantidade de pessoas que consigo atingir com os treinamentos e receber o feedback que o conteúdo ministrado ajudou de alguma forma na carreira delas, impagável.
Falando em impagável e dinheiro, eu já mencionei isso uma vez e repito, o tempo utilizado e esforço que faço pra gravar os treinamentos é absurdo, o valor cobrado não é nem de longe, o que eu conseguiria simplesmente trabalhando pra Pythian 😊, mas gosto de fazer isso, e sei que eu aprendo muito estudando e preparando o material, então, no fim considero um investimento.
Tendo isso em mente, vamos pras novidades, os 2 últimos treinamentos que gravei foram Internals 4 (Disk I/O) (o meu treinamento predileto até agora) e o +25 dicas de performance parte 6 se você ainda não comprou, agora é a hora pois em Novembro estamos com descontos de 50% em quase todos (exceto dicas parte6) os meus treinamentos, então corre que agora é a hora. É sério, tá de graça.
Pra mais detalhes (voucher) sobre os descontos acesse https://powertuning.com.br/deu-a-louca-no-gerente-mes-de-descontos-nos-cursos-da-power-tuning/
Eu sei que devido a pandemia muita gente ficou desempregada, teve redução de salário ou está passando por dificuldade financeira, pra essas pessoas, eu digo, agora é a hora de estudar e entender que conhecimento é o diferencial que pode te ajudar MUITO. Com isso em mente, se você está “quebrado” e quer fazer os meus treinamentos, me avisa, é simples assim, me manda um e-mail, ou mesmo um “Zap” (14-998180312) que a gente conversa e se for o caso, eu te dou 100% de desconto.
Abraço e cuidem-se.
Fabiano
30 tips to do a good presentation
Hi folks, yesterday I wrote this to send to a few colleagues at Pythian and I thought it may be interesting to you as well.. Some tips to do a good presentation, well, at least in my opinion 😊:
- Number one and most important… Learn how to use ZoomIt
- Increase font size on SSMS, including resultset grid
- Fullscreen on SSMS
- Add comments in your scripts to make it easier to people repro your demos, comments like “starting the magic” are valid.
- Time – A tie with ZoomIt on level of importance… There is nothing more frustrating than watch a person spend 40 minutes on first slides when you know he still have two or three demos to do…
- Time – It is VERY disrespectful to use someone else time… So, if your session ends on 50 minutes, please leave the stage in 50 minutes… If the next speaker is waiting and “is willing” to give you some time of his presentation, DON’T accept it, he is just being nice with you while you IS NOT.
- Time – If event don’t have already, ask someone to give you tips on how much time you’ve left… I usually like a sign of “30 minutes left”, “20 minutes left”, “10 minutes left” and “5 minutes left”… If necessary, use a timer app in your smartphone to help you…
- If possible (ask the organizers if it is ok to do it), try to record your session to watch it later and look for mistakes and areas to improve.
- Record yourself presenting or if possible, present to a friend and ask for tips, ask about time, demos…
- Demo – If possible, leave a “key” demo to the end … I like to keep a demo I can do in 5 minutes or 30 minutes.
- Demo vs Slides – Only slides is boring, only demos is weird (sometimes is ok)… So a balance between the two is best.
- Session abstract has to deliver what it says…
- Level is also important… There is no such a thing as a “Advanced techniques to bla bla bla – Level 200”
- As Buck Woody would say… “The main thing is to keep the main thing the main thing”. Don’t get out of focus, make sure you’re always on track with what your presentation should deliver…
- Humor is good, too much humor is not good… It is kind of an art… I’m still learning it…
- Try to use creative names on sessions… Instead of SQL Server on Linux, try something like “Does Microsoft really like penguins? SQL on Linux!”
- PowerPoint, avoid “regular” bullets… Smartarts are more interesting to read… Animations are always good, but may take lot of time to create…
- Demonstrations:
- IT HAS TO WORK! Doesn’t matter what!
- If you can’t do it because of an internet limitation, record a video of the demo and play it.
- The video recording can be used as a backup in case something goes wrong and you don’t know why the demo isn’t working.
- DON’T EVER do a live demo troubleshooting… Assume it is not working, apologies and tell people you’ll record a video of the demo and post on YouTube… PLEASE DON’T open Google to search for a solution of a problem…
- Upload the slides and demos prior to the event… then, when people ask “where can I download the material? Or when the material will be available to download”, just answer, it is already in my Blog.
- There is an interesting saying I heard on backstage of events… “Unless your name is Itzik Ben-Gan, do never type a code”, prepare it in advance and just “select + run it”…
- If for some reason you decide to change something in the demo, maybe because of a question some asked, make sure you are 100% confident on what you’re doing… and, if for some reason the code doesn’t work like you’re expecting DON’T try to fix it… Just say you’ll do it later and post on YouTube…
- Once I was doing a “live coding” (don’t do it) and it wasn’t working…after 5 minutes I decided to quit doing the demo… After watch the presentation record, I realized that the code wasn’t working because I forgot to put a semicolon (;)…
- Q &A – Always repeat questions so people in the back can understand what you are answering…
- Q &A – Don’t ever get into a two-people conversation with an attendee… There is almost always a person trying to have a free consulting and ask 10 questions… It is nice that you give him attention, but there will be another X people not getting your attention… The chances they get their phone to look at Facebook is very high.
- Tell those people you’ll be available after the session to talk about the subject.
- Q &A – Be careful with questions and the session time… If you’re getting too many questions, it may inhibit you to deliver all the content and this is more important than the questions. If you fell this is a problem, just say you’ll answer the questions at the end of the presentation.
- Q &A – Be careful with questions not related to the session… They may make you loose track of your original goal… If you have time, it maybe ok to answer them, but it may be a better idea to answer them “offline” after the session.
- Q & A – Be prepared for attendees trying to be smarter than you and ask very difficult questions… Yes, it is not very rare to see those. If they are indeed smarter than you, that’s fine, just humble tell them you’ll search for a good answer and reply offline. Don’t allow them to make you lose your confidence.
- Q & A – If you don’t know the answer, or is not certain, please don’t try to bullshit it… It is A LOT easier to just say you don’t know and you’ll reply later via e-mail…
- Sponsors are the reason the event is happening, make sure you give them the visibility they deserve.
- Don’t copy content from someone else without ASK for permission and make sure give them the credits. One hundred percent of people I know in the community will be more than glad to share their presentations/slides/demos with you, I’ve never heard of a case they denied it. So, please, just ask for it.
- Ask for feedback (evaluation forms) and make sure attendees understand how important this is to you. Don’t be a chicken and cry in your room because of a bad feedback… Learn from it 🙂
- The attendee is more important than you, they should be the reason you’re doing the presentation, not you… Self-promoting is important, but it is not the main thing. There is nothing more pleasant than hear your “teaching” helped someone to get a better job or fix a problem…
Você já procurou no Google?
Revivendo o blog,
Faz algum tempo que quero escrever sobre isso, então vamos lá…
Quando eu comecei a estudar pra trabalhar com informática, não foi fácil, fiz um curso técnico em programação que custava R$ 109,00 reais por mês, na época, eu ganhava R$119,00 trabalhando como office boy. Foi difícil, mas com certeza valeu muito a pena. Aprendi demais com o Elvis (a.k.a. Delphis), Marco e o Eduardo. Back em 2012, minhas fontes de estudo não eram muitas, e devido a falta de dinheiro pra comprar livros, os materiais que eu tinham eram a internet e livros que eu conseguia pegar na biblioteca da escola, bem como livros que meu irmão já tinha e que eu roubava…
De qualquer forma, a internet foi e continua sendo longe o principal lugar onde busco conhecimento, é incrível o que conseguimos aprender nesse mundo sem fim chamado www. Quando eu não sabia o que fazer, era só perder um tempo lendo a documentação do produto, ou no Google, ou em último caso, em fóruns …
Os fóruns technet e msdn sempre foram um excelente lugar pra tirar dúvidas e aprender com as brilhantes respostas que lá estavam… Fonte infinita de conhecimento de pessoas que estavam dispostas a perder/investir um tempo ajudando outras pessoas que estavam com dúvidas… Aprendei demais com o Galvão, Gustavo Maia, Marcelo Colla, Nilton Pinheiro, Diego Nogare e etc… Bons tempos de fóruns.
Depois de um tempo, passei a ajudar com as respostas, me sentia realizado em ajudar as pessoas a resolverem algum problema, a sensação era impagável… Anos passaram, e a coisa desandou, e cá estamos, no ponto onde quero falar.
Os fóruns msdn/technet ficaram chatos a ponto de ser insuportável ler as perguntas das mulas… Abandonei totalmente os fóruns e agora estou prestes a abandonar os grupos de WhatsApp e Telegram pelo mesmo motivo…
Minha insatisfação é só uma… As pessoas não se dão mais o trabalho de aprender a usar o produto, ou de ler a documentação do produto, ou mesmo de usar o GOOGLE pra tirar as dúvidas… Simplesmente correm pro grupo de Zap e enviam suas dúvidas sem ao menos perder 1 minuto digitando a dúvida no Google … A resposta de 95% das dúvidas que vejo nesses grupos está na primeira página do Google. O que aconteceu? Por que as pessoas estão assim? Eu ainda não consegui entender isso.
Alguns exemplos de perguntas:
- Como faço pra atualizar uma coluna na tabela?
- Meu servidor SQL está utilizando toda a memória disponível… O que faço?
- Qual valor uso no MAXDOP?
Também temos aqueles que acham que tem o direito de uma consultoria gratuita… Semanalmente eu recebo dezenas de perguntas no privado, linkedin, facebook, whatsapp, telegrama e e-mail… Veja, eu sempre que possível tento responder, mas tem gente que me manda um código com 5 mil linhas e pede pra eu otimizar… Pera? Eim? … Ou pede ajuda pra eu conectar no servidor delas porque está lento… Eim?
Se me permitem, deixa eu tentar ajudar… Antes de perguntar qualquer cosia pra alguém, POR FAVOR, tente fazer o seguinte:
- Já procurou a resposta na documentação do produto?
- Já procurou extensivamente na internet? Google, Youtube e etc…
- Você entendeu o que quer perguntar? Por ex., antes de querer saber onde usar o hint OPTION (MAXDOP), já procurou saber o que ele faz? O que é paralelismo?
Bom, ficam ai meus 2 cents…
Abs.
Fabiano
Artigo novo no Simple-Talk, Tempdb
E finalmente depois de 5 anos saiu artigo novo meu no Simple-Talk 🙂 … go go go..
https://www.red-gate.com/simple-talk/sql/performance/tempdb-heres-a-problem-you-didnt-know-you-have/
Hope you like it!
Abs.
Fabiano