Qual é o uso dos dados no .ldf
arquivo (log) após a restauração de um backup completo. Estou planejando reduzir os arquivos de log depois de restaurar o backup completo no meu servidor dev.
Existe algum efeito colateral para isso?
Qual é o uso dos dados no .ldf
arquivo (log) após a restauração de um backup completo. Estou planejando reduzir os arquivos de log depois de restaurar o backup completo no meu servidor dev.
Existe algum efeito colateral para isso?
Tentando obter o id da sessão dos trabalhos em execução
;with JobDetails as
(
select Job_Id = left(intr1,charindex(':',intr1)-1),
Step = substring(intr1,charindex(':',intr1)+1,charindex(')',intr1)-charindex(':',intr1)-1),
SessionId = spid
from master.dbo.sysprocesses x
cross apply (select replace(x.program_name,'SQLAgent - TSQL JobStep (Job ','')) cs (intr1)
where spid > 50 and x.program_name like 'SQLAgent - TSQL JobStep (Job %'
)
select *
from msdb.dbo.sysjobs j
inner join JobDetails jd on j.job_id = jd.Job_Id
mas dá o seguinte erro
Msg 8169, Level 16, State 2, Line 47 A conversão falhou ao converter de uma cadeia de caracteres para identificador exclusivo.
Eu tentei converter o job_id
para varbinary
, mas não produz resultado
;with JobDetails as
(
select Job_Id = left(intr1,charindex(':',intr1)-1),
Step = substring(intr1,charindex(':',intr1)+1,charindex(')',intr1)-charindex(':',intr1)-1),
SessionId = spid
from master.dbo.sysprocesses x
cross apply (select replace(x.program_name,'SQLAgent - TSQL JobStep (Job ','')) cs (intr1)
where spid > 50 and x.program_name like 'SQLAgent - TSQL JobStep (Job %'
)
select *
from msdb.dbo.sysjobs j
inner join JobDetails jd on cast(j.job_id as varbinary) = jd.Job_Id
mas quando eu copio cole job_id
um cte
assim
select job_id, name
from msdb..sysjobs
where job_id = 0x128A47A31EAB8F4DA1AD852093D815F5
funciona . _ Alguma ideia de como corrigir essa consulta
Estou tentando otimizar um procedimento. Existem 3 consultas de atualização diferentes presentes no procedimento.
update #ResultSet
set MajorSector = case
when charindex(' ', Sector) > 2 then rtrim(ltrim(substring(Sector, 0, charindex(' ', Sector))))
else ltrim(rtrim(sector))
end
update #ResultSet
set MajorSector = substring(MajorSector, 5, len(MajorSector)-4)
where left(MajorSector,4) in ('(00)','(01)','(02)','(03)','(04)','(05)','(06)','(07)','(08)','(09)')
update #ResultSet
set MajorSector = substring(MajorSector, 4, len(MajorSector)-3)
where left(MajorSector,3) in ('(A)','(B)','(C)','(D)','(E)','(F)','(G)','(H)','(I)','(J)','(K)','(L)','(M)','(N)','(O)','(P)','(Q)','(R)','(S)','(T)','(U)','(V)','(W)','(X)','(Y)','(Z)')
Para concluir todas as três consultas de atualização, leva menos de 10 segundos .
Plano de execução para todas as três consultas de atualização.
https://www.brentozar.com/pastetheplan/?id=r11BLfq7b
O que planejei é mudar as três consultas de atualização diferentes em uma única consulta de atualização, para que a E/S possa ser reduzida.
;WITH ResultSet
AS (SELECT CASE
WHEN LEFT(temp_MajorSector, 4) IN ( '(00)', '(01)', '(02)', '(03)', '(04)', '(05)', '(06)', '(07)', '(08)', '(09)' )
THEN Substring(temp_MajorSector, 5, Len(temp_MajorSector) - 4)
WHEN LEFT(temp_MajorSector, 3) IN ( '(A)', '(B)', '(C)', '(D)','(E)', '(F)', '(G)', '(H)','(I)', '(J)', '(K)', '(L)','(M)', '(N)', '(O)', '(P)','(Q)', '(R)', '(S)', '(T)','(U)', '(V)', '(W)', '(X)','(Y)', '(Z)' )
THEN Substring(temp_MajorSector, 4, Len(temp_MajorSector) - 3)
ELSE temp_MajorSector
END AS temp_MajorSector,
MajorSector
FROM (SELECT temp_MajorSector = CASE
WHEN Charindex(' ', Sector) > 2 THEN Rtrim(Ltrim(Substring(Sector, 0, Charindex(' ', Sector))))
ELSE Ltrim(Rtrim(sector))
END,
MajorSector
FROM #ResultSet)a)
UPDATE ResultSet
SET MajorSector = temp_MajorSector
Mas isso leva cerca de 1 minuto para ser concluído. Verifiquei o plano de execução, é idêntico à primeira consulta de atualização .
Plano de execução para a consulta acima:
https://www.brentozar.com/pastetheplan/?id=SJvttz9QW
Alguém pode explicar porque é lento?
Dados fictícios para teste:
If object_id('tempdb..#ResultSet') is not null
drop table #ResultSet
;WITH lv0 AS (SELECT 0 g UNION ALL SELECT 0)
,lv1 AS (SELECT 0 g FROM lv0 a CROSS JOIN lv0 b) -- 4
,lv2 AS (SELECT 0 g FROM lv1 a CROSS JOIN lv1 b) -- 16
,lv3 AS (SELECT 0 g FROM lv2 a CROSS JOIN lv2 b) -- 256
,lv4 AS (SELECT 0 g FROM lv3 a CROSS JOIN lv3 b) -- 65,536
,lv5 AS (SELECT 0 g FROM lv4 a CROSS JOIN lv4 b) -- 4,294,967,296
,Tally (n) AS (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM lv5)
SELECT CONVERT(varchar(255), NEWID()) as Sector,cast('' as varchar(1000)) as MajorSector
into #ResultSet
FROM Tally
where n <= 242906 -- my original table record count
ORDER BY n;
Nota: Como não são meus dados originais, os horários que mencionei acima podem ser um pouco diferentes. Ainda assim, a consulta de atualização única é muito mais lenta que as três primeiras.
Tentei executar as consultas mais de 10 vezes para garantir que fatores externos não afetem o desempenho. Todas as 10 primeiras três atualizações foram executadas muito mais rapidamente do que a última atualização única.
Existe uma consulta para verificar quais trabalhos foram executados entre determinados horários. Eu posso verificar os trabalhos que estão agendados entre dois horários, mas não quero isso.
Exemplo Eu quero saber quais são os Jobs que foram executados entre 16:00:00
e17:00:00
Pode haver casos em que o trabalho agendado 15:00:00
pode ser executado por mais de 1 hora. Eu pesquisei no google tudo o que consegui são trabalhos que estão agendados entre duas vezes
Eu tenho uma consulta que é um pouco mais lenta.
SELECT b.BreakdownClassificationId,
k.IsinCode,
k.SedolCode,
ClassificationDate,
NAME,
InstrumentType,
GeographicalLocation,
CapSize,
Currency,
ExchangeName,
HoldingDomicile,
MaturityDate,
Sector,
MajorSector
FROM #BreakdownSet b
OUTER apply (SELECT TOP 1 IsinCode,
SedolCode,
ClassificationDate,
NAME,
InstrumentType,
GeographicalLocation,
CapSize CapSize,
Currency,
ExchangeName,
HoldingDomicile,
MaturityDate,
Sector,
MajorSector
FROM dbfinex.dbo.PfPortfolioHoldingClassificationFtid x WITH (nolock)
WHERE ( x.isincode > ''
AND x.isincode = b.breakdowncode )
OR ( x.sedolcode > ''
AND x.sedolcode = b.breakdowncode )
OR ( x.sedolcode > ''
AND x.sedolcode = b.sedolcode )
OR ( x.isincode > ''
AND x.isincode = b.isincode )
ORDER BY CASE
WHEN x.sedolcode = b.breakdowncode THEN 1
WHEN x.isincode = b.breakdowncode THEN 2
WHEN x.sedolcode = b.sedolcode THEN 3
WHEN x.isincode = b.isincode THEN 4
ELSE 5
END,
classificationdate DESC) k
Plano de execução
Order By
dentro do Cross Apply
é muito caro, existe alguma maneira melhor de escrever essa consulta?
Existe uma maneira de descobrir quantas vezes o gatilho é chamado em uma sessão específica? Nosso aplicativo ETL está inserindo registros como cada linha em vez de instrução (ou seja) Se 100 registros devem ser inseridos, acho que o ETL emite 100 instruções de inserção em vez de inserir em um único lote. Portanto, o gatilho também é chamado 100 vezes. Eu só quero confirmar que o gatilho é chamado 100 vezes.
Eu tenho uma ideia de alterar o gatilho para ter contador e armazená-lo em uma tabela para encontrar o número de chamadas de gatilho.
Existe uma maneira nativa de encontrar isso?
Recentemente, usamos uma ferramenta de revisão de código sql em nosso banco de dados. Está sugerindo usar SP_EXECUTESQL
em vez de EXEC
.
Eu sei que SP_EXECUTESQL
nos ajuda a evitar injeção de sql. Existe alguma diferença no desempenho ao usar EXEC
vs.SP_EXECUTESQL
Considere que eu tenho login chamado sql_login. Posso bloquear sql_login
o login após 5
tentativas malsucedidas de login.
Quando criamos um login podemos ver que existe uma opção chamada política de senhas verifique a imagem. Mas não há nada mencionado sobre o bloqueio de senha
Existe uma opção no Sql Server para bloquear um login após N
tentativas de login malsucedidas
Estou tentando calcular o total em execução. Mas deve ser redefinido quando a soma cumulativa for maior que outro valor de coluna
create table #reset_runn_total
(
id int identity(1,1),
val int,
reset_val int,
grp int
)
insert into #reset_runn_total
values
(1,10,1),
(8,12,1),(6,14,1),(5,10,1),(6,13,1),(3,11,1),(9,8,1),(10,12,1)
SELECT Row_number()OVER(partition BY grp ORDER BY id)AS rn,*
INTO #test
FROM #reset_runn_total
Detalhes do índice:
CREATE UNIQUE CLUSTERED INDEX ix_load_reset_runn_total
ON #test(rn, grp)
dados de amostra
+----+-----+-----------+-----+
| id | val | reset_val | Grp |
+----+-----+-----------+-----+
| 1 | 1 | 10 | 1 |
| 2 | 8 | 12 | 1 |
| 3 | 6 | 14 | 1 |
| 4 | 5 | 10 | 1 |
| 5 | 6 | 13 | 1 |
| 6 | 3 | 11 | 1 |
| 7 | 9 | 8 | 1 |
| 8 | 10 | 12 | 1 |
+----+-----+-----------+-----+
Resultado esperado
+----+-----+-----------------+-------------+
| id | val | reset_val | Running_tot |
+----+-----+-----------------+-------------+
| 1 | 1 | 10 | 1 |
| 2 | 8 | 12 | 9 | --1+8
| 3 | 6 | 14 | 15 | --1+8+6 -- greater than reset val
| 4 | 5 | 10 | 5 | --reset
| 5 | 6 | 13 | 11 | --5+6
| 6 | 3 | 11 | 14 | --5+6+3 -- greater than reset val
| 7 | 9 | 8 | 9 | --reset -- greater than reset val
| 8 | 10 | 12 | 10 | --reset
+----+-----+-----------------+-------------+
Consulta:
Eu obtive o resultado usando Recursive CTE
. A pergunta original está aqui https://stackoverflow.com/questions/42085404/reset-running-total-based-on-another-column
;WITH cte
AS (SELECT rn,id,
val,
reset_val,
grp,
val AS running_total,
Iif (val > reset_val, 1, 0) AS flag
FROM #test
WHERE rn = 1
UNION ALL
SELECT r.*,
Iif(c.flag = 1, r.val, c.running_total + r.val),
Iif(Iif(c.flag = 1, r.val, c.running_total + r.val) > r.reset_val, 1, 0)
FROM cte c
JOIN #test r
ON r.grp = c.grp
AND r.rn = c.rn + 1)
SELECT *
FROM cte
Existe alguma alternativa melhor T-SQL
sem usar CLR
.?
Considere a seguinte configuração. Existem três tabelas envolvidas #CCP_DETAILS_TEMP
, Period
eACTUALS_DETAILS
#CCP_DETAILS_TEMP
terá 50000
registros, ACTUALS_DETAILS
pode ter 5000000
registros e period
tabela terá 2000
registros
Detalhes do índice:
CREATE UNIQUE CLUSTERED INDEX IX_CCP_DETAILS_TEMP
ON #CCP_DETAILS_TEMP (CCP_DETAILS_SID)
CREATE NONCLUSTERED INDEX IXN_ACTUALS_DETAILS_PERIOD_SID_RS_MODEL_SID_CCP_DETAILS_SID_QUANTITY_INCLUSION
ON ACTUALS_DETAILS (PERIOD_SID, CCP_DETAILS_SID, RS_MODEL_SID, QUANTITY_INCLUSION)
INCLUDE( SALES, QUANTITY, DISCOUNT)
CREATE UNIQUE CLUSTERED INDEX IX_PERIOD
ON PERIOD (PERIOD_SID)
Eu tenho um requisito para o qual escrevi três maneiras diferentes de alcançar o resultado. Agora quero saber qual é melhor.
Todas as três consultas estão sendo executadas mais ou menos no mesmo tempo. Preciso de alguns conselhos de especialistas sobre qual deles terá melhor desempenho. Existe alguma desvantagem em qualquer uma das abordagens
Abordagem 1: Outer Apply
Tempo gasto: 4615 Milli Seconds
SELECT c.CCP_DETAILS_SID,
A.PERIOD_SID,
SALES,
QUANTITY
FROM #CCP_DETAILS_TEMP c
CROSS JOIN (SELECT PERIOD_SID
FROM BPIGTN_GAL_APP_DEV_ARM..PERIOD
WHERE PERIOD_SID BETWEEN 577 AND 624)A
OUTER apply (SELECT Sum(SALES),
Sum(QUANTITY)
FROM [DBO].[ACTUALS_DETAILS] ad
WHERE a.PERIOD_SID = ad.PERIOD_SID
AND ad.CCP_DETAILS_SID = c.CCP_DETAILS_SID
AND QUANTITY_INCLUSION = 'Y') oa (sales, quantity)
Estatísticas da consulta:
Tabela 'PERÍODO'. Contagem de varredura 1, leituras lógicas 2, leituras físicas 0, leituras antecipadas 0, leituras lógicas lob 0, leituras físicas lob 0, leituras antecipadas lob 0.
Tabela '#CCP_DETAILS_TEMP'. Contagem de varredura 16, leituras lógicas 688, leituras físicas 0, leituras antecipadas 0, leituras lógicas lob 0, leituras físicas lob 0, leituras antecipadas lob 0.
Tabela 'Mesa de trabalho'. Contagem de varredura 16, leituras lógicas 807232, leituras físicas 0, leituras antecipadas 0, leituras lógicas lob 0, leituras físicas lob 0, leituras antecipadas lob 0.
Tabela 'ACTUALS_DETAILS'. Contagem de varredura 1200000, leituras lógicas 3859053, leituras físicas 0, leituras antecipadas 0, leituras lógicas lob 0, leituras físicas lob 0, leituras antecipadas lob 0.
Tabela 'Mesa de trabalho'. Contagem de varredura 0, leituras lógicas 0, leituras físicas 0, leituras antecipadas 0, leituras lógicas lob 0, leituras físicas lob 0, leituras antecipadas lob 0.
Tabela 'Mesa de trabalho'. Contagem de varredura 0, leituras lógicas 0, leituras físicas 0, leituras antecipadas 0, leituras lógicas lob 0, leituras físicas lob 0, leituras antecipadas lob 0.
Tempos de execução do SQL Server: tempo de CPU = 36796 ms, tempo decorrido = 4615 ms.
Tempos de execução do SQL Server: tempo de CPU = 0 ms, tempo decorrido = 0 ms.
Abordagem 2: Left Join
Tempo gasto: 4293 Milli Seconds
SELECT c.CCP_DETAILS_SID,
A.PERIOD_SID,
Sum(SALES),
Sum(QUANTITY)
FROM #CCP_DETAILS_TEMP c
CROSS JOIN (SELECT PERIOD_SID
FROM BPIGTN_GAL_APP_DEV_ARM..PERIOD
WHERE PERIOD_SID BETWEEN 577 AND 624) a
LEFT JOIN [ACTUALS_DETAILS] ad
ON a.PERIOD_SID = ad.PERIOD_SID
AND ad.CCP_DETAILS_SID = c.CCP_DETAILS_SID
AND QUANTITY_INCLUSION = 'Y'
GROUP BY c.CCP_DETAILS_SID,
A.PERIOD_SID
Estatísticas da consulta:
Tabela 'ACTUALS_DETAILS'. Contagem de varredura 17, leituras lógicas 37134, leituras físicas 0, leituras antecipadas 0, leituras lógicas lob 0, leituras físicas lob 0, leituras antecipadas lob 0.
Tabela 'PERÍODO'. Contagem de varredura 1, leituras lógicas 2, leituras físicas 0, leituras antecipadas 0, leituras lógicas lob 0, leituras físicas lob 0, leituras antecipadas lob 0.
Tabela '#CCP_DETAILS_TEMP'. Contagem de varredura 16, leituras lógicas 688, leituras físicas 0, leituras antecipadas 0, leituras lógicas lob 0, leituras físicas lob 0, leituras antecipadas lob 0.
Tabela 'Mesa de trabalho'. Contagem de varredura 16, leituras lógicas 807232, leituras físicas 0, leituras antecipadas 0, leituras lógicas lob 0, leituras físicas lob 0, leituras antecipadas lob 0.
Tabela 'Arquivo de trabalho'. Contagem de varredura 0, leituras lógicas 0, leituras físicas 0, leituras antecipadas 0, leituras lógicas lob 0, leituras físicas lob 0, leituras antecipadas lob 0.
Tabela 'Mesa de trabalho'. Contagem de varredura 0, leituras lógicas 0, leituras físicas 0, leituras antecipadas 0, leituras lógicas lob 0, leituras físicas lob 0, leituras antecipadas lob 0.
Tempos de execução do SQL Server: tempo de CPU = 7983 ms, tempo decorrido = 4293 ms.
Tempos de execução do SQL Server: tempo de CPU = 0 ms, tempo decorrido = 0 ms.
Abordagem 3: agregando a primeira e a junção à esquerda:
Tempo gasto: 4200 Milli Seconds
SELECT c.CCP_DETAILS_SID,
A.PERIOD_SID,
SALES,
QUANTITY
FROM #CCP_DETAILS_TEMP c
CROSS JOIN (SELECT PERIOD_SID
FROM BPIGTN_GAL_APP_DEV_ARM..PERIOD
WHERE PERIOD_SID BETWEEN 577 AND 624) a
LEFT JOIN (SELECT CCP_DETAILS_SID,
PERIOD_SID,
Sum(SALES) SALES,
Sum(QUANTITY) QUANTITY
FROM [ACTUALS_DETAILS] ad
WHERE QUANTITY_INCLUSION = 'Y'
GROUP BY CCP_DETAILS_SID,
PERIOD_SID) ad
ON a.PERIOD_SID = ad.PERIOD_SID
AND ad.CCP_DETAILS_SID = c.CCP_DETAILS_SID
Estatísticas da consulta:
Tabela 'ACTUALS_DETAILS'. Contagem de varredura 17, leituras lógicas 37134, leituras físicas 0, leituras antecipadas 0, leituras lógicas lob 0, leituras físicas lob 0, leituras antecipadas lob 0.
Tabela 'Mesa de trabalho'. Contagem de varredura 16, leituras lógicas 807232, leituras físicas 0, leituras antecipadas 0, leituras lógicas lob 0, leituras físicas lob 0, leituras antecipadas lob 0.
Tabela 'Arquivo de trabalho'. Contagem de varredura 0, leituras lógicas 0, leituras físicas 0, leituras antecipadas 0, leituras lógicas lob 0, leituras físicas lob 0, leituras antecipadas lob 0.
Tabela 'PERÍODO'. Contagem de varredura 1, leituras lógicas 2, leituras físicas 0, leituras antecipadas 0, leituras lógicas lob 0, leituras físicas lob 0, leituras antecipadas lob 0.
Tabela '#CCP_DETAILS_TEMP'. Contagem de varredura 16, leituras lógicas 688, leituras físicas 0, leituras antecipadas 0, leituras lógicas lob 0, leituras físicas lob 0, leituras antecipadas lob 0.
Tabela 'Mesa de trabalho'. Contagem de varredura 0, leituras lógicas 0, leituras físicas 0, leituras antecipadas 0, leituras lógicas lob 0, leituras físicas lob 0, leituras antecipadas lob 0.
Tempos de execução do SQL Server: tempo de CPU = 7731 ms, tempo decorrido = 4200 ms.
Tempos de execução do SQL Server: tempo de CPU = 0 ms, tempo decorrido = 0 ms.
Como o número de etapas do histograma é decidido em Estatísticas no SQL Server?
Por que é restrito a 200 etapas, embora minha coluna de chave tenha mais de 200 valores distintos? Existe algum fator decisivo?
Demonstração
Definição de esquema
CREATE TABLE histogram_step
(
id INT IDENTITY(1, 1),
name VARCHAR(50),
CONSTRAINT pk_histogram_step PRIMARY KEY (id)
)
Inserindo 100 registros na minha tabela
INSERT INTO histogram_step
(name)
SELECT TOP 100 name
FROM sys.syscolumns
Atualizando e verificando as estatísticas
UPDATE STATISTICS histogram_step WITH fullscan
DBCC show_statistics('histogram_step', pk_histogram_step)
Etapas do histograma:
+--------------+------------+---------+---------------------+----------------+
| RANGE_HI_KEY | RANGE_ROWS | EQ_ROWS | DISTINCT_RANGE_ROWS | AVG_RANGE_ROWS |
+--------------+------------+---------+---------------------+----------------+
| 1 | 0 | 1 | 0 | 1 |
| 3 | 1 | 1 | 1 | 1 |
| 5 | 1 | 1 | 1 | 1 |
| 7 | 1 | 1 | 1 | 1 |
| 9 | 1 | 1 | 1 | 1 |
| 11 | 1 | 1 | 1 | 1 |
| 13 | 1 | 1 | 1 | 1 |
| 15 | 1 | 1 | 1 | 1 |
| 17 | 1 | 1 | 1 | 1 |
| 19 | 1 | 1 | 1 | 1 |
| 21 | 1 | 1 | 1 | 1 |
| 23 | 1 | 1 | 1 | 1 |
| 25 | 1 | 1 | 1 | 1 |
| 27 | 1 | 1 | 1 | 1 |
| 29 | 1 | 1 | 1 | 1 |
| 31 | 1 | 1 | 1 | 1 |
| 33 | 1 | 1 | 1 | 1 |
| 35 | 1 | 1 | 1 | 1 |
| 37 | 1 | 1 | 1 | 1 |
| 39 | 1 | 1 | 1 | 1 |
| 41 | 1 | 1 | 1 | 1 |
| 43 | 1 | 1 | 1 | 1 |
| 45 | 1 | 1 | 1 | 1 |
| 47 | 1 | 1 | 1 | 1 |
| 49 | 1 | 1 | 1 | 1 |
| 51 | 1 | 1 | 1 | 1 |
| 53 | 1 | 1 | 1 | 1 |
| 55 | 1 | 1 | 1 | 1 |
| 57 | 1 | 1 | 1 | 1 |
| 59 | 1 | 1 | 1 | 1 |
| 61 | 1 | 1 | 1 | 1 |
| 63 | 1 | 1 | 1 | 1 |
| 65 | 1 | 1 | 1 | 1 |
| 67 | 1 | 1 | 1 | 1 |
| 69 | 1 | 1 | 1 | 1 |
| 71 | 1 | 1 | 1 | 1 |
| 73 | 1 | 1 | 1 | 1 |
| 75 | 1 | 1 | 1 | 1 |
| 77 | 1 | 1 | 1 | 1 |
| 79 | 1 | 1 | 1 | 1 |
| 81 | 1 | 1 | 1 | 1 |
| 83 | 1 | 1 | 1 | 1 |
| 85 | 1 | 1 | 1 | 1 |
| 87 | 1 | 1 | 1 | 1 |
| 89 | 1 | 1 | 1 | 1 |
| 91 | 1 | 1 | 1 | 1 |
| 93 | 1 | 1 | 1 | 1 |
| 95 | 1 | 1 | 1 | 1 |
| 97 | 1 | 1 | 1 | 1 |
| 99 | 1 | 1 | 1 | 1 |
| 100 | 0 | 1 | 0 | 1 |
+--------------+------------+---------+---------------------+----------------+
Como podemos ver, existem 53 passos no histograma.
Novamente inserindo alguns milhares de registros
INSERT INTO histogram_step
(name)
SELECT TOP 10000 b.name
FROM sys.syscolumns a
CROSS JOIN sys.syscolumns b
Atualizando e verificando as estatísticas
UPDATE STATISTICS histogram_step WITH fullscan
DBCC show_statistics('histogram_step', pk_histogram_step)
Agora as etapas do histograma são reduzidas para 4 etapas
+--------------+------------+---------+---------------------+----------------+
| RANGE_HI_KEY | RANGE_ROWS | EQ_ROWS | DISTINCT_RANGE_ROWS | AVG_RANGE_ROWS |
+--------------+------------+---------+---------------------+----------------+
| 1 | 0 | 1 | 0 | 1 |
| 10088 | 10086 | 1 | 10086 | 1 |
| 10099 | 10 | 1 | 10 | 1 |
| 10100 | 0 | 1 | 0 | 1 |
+--------------+------------+---------+---------------------+----------------+
Novamente inserindo alguns milhares de registros
INSERT INTO histogram_step
(name)
SELECT TOP 100000 b.name
FROM sys.syscolumns a
CROSS JOIN sys.syscolumns b
Atualizando e verificando as estatísticas
UPDATE STATISTICS histogram_step WITH fullscan
DBCC show_statistics('histogram_step', pk_histogram_step)
Agora as etapas do histograma são reduzidas para 3 etapas
+--------------+------------+---------+---------------------+----------------+
| RANGE_HI_KEY | RANGE_ROWS | EQ_ROWS | DISTINCT_RANGE_ROWS | AVG_RANGE_ROWS |
+--------------+------------+---------+---------------------+----------------+
| 1 | 0 | 1 | 0 | 1 |
| 110099 | 110097 | 1 | 110097 | 1 |
| 110100 | 0 | 1 | 0 | 1 |
+--------------+------------+---------+---------------------+----------------+
Alguém pode me dizer como essas etapas são decididas?
Estou tentando entender as divisões de página no SQL Server, lendo O QUE É UMA DIVISÃO DE PÁGINA? O QUE ACONTECE? POR QUE ACONTECE? POR QUE SE PREOCUPAR? por Tony Rogerson
CREATE TABLE mytest
(
something_to_see_in_data CHAR(5) NOT NULL CONSTRAINT pk_mytest PRIMARY KEY CLUSTERED,
filler VARCHAR(3000) NOT NULL
)
go
insert mytest ( something_to_see_in_data, filler ) values( '00001', replicate( 'A', 3000 ) )
insert mytest ( something_to_see_in_data, filler ) values( '00002', replicate( 'B', 1000 ) )
insert mytest ( something_to_see_in_data, filler ) values( '00003', replicate( 'C', 3000 ) )
go
Para verificar as páginas da minha tabela:
DBCC IND ( 0, 'mytest', 1);
+---------+---------+--------+--------+------------+---------+-----------------+-------------------+----------------+----------+------------+
| PageFID | PagePID | IAMFID | IAMPID | ObjectID | IndexID | PartitionNumber | PartitionID | iam_chain_type | PageType | IndexLevel |
+---------+---------+--------+--------+------------+---------+-----------------+-------------------+----------------+----------+------------+
| 1 | 3520 | NULL | NULL | 2065259704 | 1 | 1 | 72057595357560832 | In-row data | 10 | NULL |
| 1 | 3519 | 1 | 3520 | 2065259704 | 1 | 1 | 72057595357560832 | In-row data | 1 | 0 |
+---------+---------+--------+--------+------------+---------+-----------------+-------------------+----------------+----------+------------+
Para verificar os detalhes da página de dados:
dbcc traceon( 3604 )
go
DBCC page( 0, 1, 3519, 1 ) with tableresults
Desvio:
Slot 0, Offset 0x60, Length 3016, DumpStyle BYTE
Slot 1, Offset 0xc28, Length 1016, DumpStyle BYTE
Slot 2, Offset 0x1020, Length 3016, DumpStyle BYTE
Atualizar um dos registros, para que não caiba na página atual, e ocorrerá a divisão da página (ou seja, será criada uma nova página?
update mytest
set filler = replicate( 'B', 3000 )
where something_to_see_in_data = '00002'
Agora verificando as páginas novamente:
DBCC IND ( 0, 'mytest', 1);
+---------+---------+--------+--------+------------+---------+-----------------+-------------------+----------------+----------+------------+
| PageFID | PagePID | IAMFID | IAMPID | ObjectID | IndexID | PartitionNumber | PartitionID | iam_chain_type | PageType | IndexLevel |
+---------+---------+--------+--------+------------+---------+-----------------+-------------------+----------------+----------+------------+
| 1 | 3520 | NULL | NULL | 2065259704 | 1 | 1 | 72057595357560832 | In-row data | 10 | NULL |
| 1 | 3519 | 1 | 3520 | 2065259704 | 1 | 1 | 72057595357560832 | In-row data | 1 | 0 |
| 1 | 3521 | 1 | 3520 | 2065259704 | 1 | 1 | 72057595357560832 | In-row data | 2 | 1 |
| 1 | 3522 | 1 | 3520 | 2065259704 | 1 | 1 | 72057595357560832 | In-row data | 1 | 0 |
+---------+---------+--------+--------+------------+---------+-----------------+-------------------+----------------+----------+------------+
Como podemos ver, duas novas páginas foram criadas:
3521 -- Index page
3522 -- Data page
Eu posso entender o motivo por trás da criação de um novo Data page(3522)
porque meus dados têm mais de 8kb, então uma nova página foi criada.
Qual é a utilidade da página Índice e quando ela será criada? Fiz muitas pesquisas no Google, não há documentação adequada na página de índice. É para manter o B-Tree?
Temos um servidor executando uma única instância SQL SERVER
no ambiente de produção.
Estamos planejando criar outra instância SQL SERVER
no mesmo servidor.
Minha pergunta, temos que comprar uma nova licença ou a licença existente é boa o suficiente?
Estou usando SQL SERVER 2012
tenho meu Auto Update Stats
ON no meu banco de dados.
No link abaixo, aprendi que as estatísticas de atualização automática serão acionadas para cada SQRT(1000 * Table rows)
alteração nas linhas da tabela.
https://blogs.msdn.microsoft.com/srgolla/2012/09/04/sql-server-statistics-explained/
Criei uma tabela com 1000 registros
SELECT TOP 500 Row_number()OVER (ORDER BY (SELECT NULL)) rn,
name
INTO stst
FROM sys.objects
Criando estatísticas
CREATE STATISTICS rn
ON stst (rn)
CREATE STATISTICS name
ON stst (name)
Verificando as estatísticas criadas
DBCC show_statistics('stst', rn) -- Rows 500
DBCC show_statistics('stst', name) -- Rows 500
De acordo com a fórmula
select SQRT(1000 * 500) -- 707.106781186548
Portanto, se eu adicionar/modificar 707.106781186548
registros em minha tabela, as estatísticas de atualização automática devem disparar
Adicione 1000
mais registros à minha tabela, o que deve ser mais do que suficiente para dispararauto update stats
INSERT INTO stst(rn,name)
SELECT TOP 1000 Row_number()OVER (ORDER BY (SELECT NULL)) rn,
a.name
FROM sys.objects a
Para disparar oauto update stats
Select * from stst
Verificando as estatísticas
DBCC show_statistics('stst', rn) -- Rows 500
DBCC show_statistics('stst', name) -- Rows 500
Infelizmente ainda Rows
é o 500
único.
Mesmo depois de inserir 1000
registros em minha tabela, o que é obviamente maior do que 707.106781186548
durante a execução, SELECT
por que as estatísticas de atualização automática não dispararam? O que estou perdendo aqui
Existe alguma diferença entre atualizar as estatísticas de uma tabela usando sp_updatestats
sem reamostragem e atualizar as estatísticas da tabela usando UPDATE STATISTICS
semsample options(FULLSCAN,SAMPLE PERCENT,RESAMPLE)
exec sp_updatestats vs atualização de estatísticas tablename
atualizar as tabelas usando sp_updatestats
o valor padrão NO
atualizará as estatísticas com a taxa de amostragem padrão.
da mesma forma, atualizar as estatísticas da tabela usando UPDATE STATISTICS
sem sample options(FULLSCAN,SAMPLE PERCENT,RESAMPLE)
também atualizará as estatísticas da tabela com a amostragem padrão.
Então, há alguma diferença entre os dois métodos? Estou perdendo alguma coisa aqui?
Atualizar :
Eu sei que sp_updatestats
roda em todas as tabelas, mas usando UPDATE STATISTICS
podemos atualizar as estatísticas de uma tabela específica.
Do MSDN :
Quando nenhuma das opções de amostra
(SAMPLE, FULLSCAN, RESAMPLE)
é especificada, o otimizador de consulta faz uma amostra dos dados e calcula o tamanho da amostra por padrão.
Como identificar o tamanho da amostra padrão das estatísticas?
Procurei no MSDN, mas não encontrei nenhuma fórmula ou método para identificar o tamanho da amostra padrão. Em todos os lugares, existem apenas fórmulas presentes para acionar a atualização automática de estatísticas. Qualquer indicação será útil.
Existe alguma diferença entre o Statistics
que foi criado automaticamente pelo otimizador de consulta e o que foi criado com CREATE STATISTICS
instrução.
As estatísticas criadas manualmente serão atualizadas automaticamente quando AUTO_UPDATE_STATISTICS
for ON
. Existe alguma vantagem um sobre o outro. Pesquisei no Google e no MSDN não entendi muito sobre a diferença.
Por que estou perguntando aqui é que estamos mantendo um script que usamos para criar estatísticas manualmente após cada script de criação de tabela. Mas, em alguns scripts, perdemos a manutenção do script de estatísticas, de modo que poucas estatísticas foram geradas automaticamente. Isso terá um impacto
Referências
Meu SSMS não está se conectando a um servidor específico, X
exceto X
que está se conectando a todos os outros servidores. Não foi possível encontrar a causa raiz desse problema, alguém tem uma ideia aqui?
O cara sentado ao meu lado pode se conectar ao X
servidor. Só para mim não está conectando.
Nota: Antes de uma hora, posso me conectar ao mesmo X
servidor.
Detalhes do meu cliente ssms
Microsoft SQL Server 2012 - 11.0.5058.0 (X64) 14 de maio de 2014 18:34:29 Copyright (c) Microsoft Corporation Developer Edition (64 bits) no Windows NT 6.2 (Build 9200:)
Erro estou recebendo
Qualquer ajuda é muito apreciada.
Fui ao prompt de comando e digitei ping X
. Está voltando com Request Timed Out 4 vezes. O servidor não está inoperante; meu vizinho pode se conectar ao mesmo X
servidor que não está se conectando a mim.