Estou usando o MS SQL e preciso executar várias consultas na mesma tabela com diferentes critérios. Inicialmente, executei cada consulta na tabela original, embora todas compartilhem alguma filtragem (por exemplo, data, status). Isso levou muito tempo (cerca de 2 minutos).
Existem duplicatas nas linhas de dados e todos os índices NÃO SÃO CLUSTERADOS. Estou interessado apenas em 4 colunas para meus critérios e o resultado deve gerar apenas a contagem, para todas as consultas.
colunas necessário: TABLE
, FIELD
, AFTER
, DATE
, e existe um índice em cada um dos DATE
e TABLE
.
Depois de criar uma tabela temporária com apenas os campos necessários, ela caiu para 1:40 minutos, o que ainda é muito ruim.
CREATE TABLE #TEMP
(
TABLE VARCHAR(30) NULL,
FIELD VARCHAR(30) NULL,
AFTER VARCHAR(1000) NULL,
DATE DATETIME,
SORT_ID INT IDENTITY(1,1)
)
CREATE CLUSTERED INDEX IX_ADT ON #TEMP(SORT_ID)
INSERT INTO #TEMP (TABLE, FIELD, AFTER, DATE)
SELECT TABLE, FIELD, AFTER, DATE
FROM mytbl WITH (NOLOCK)
WHERE TABLE = 'OTB' AND
FIELD = 'STATUS'
Executar isto -> (216598 linhas afetadas)
Como nem todas as consultas dependem do período, não o incluí na consulta. O problema é que está demorando bem acima de 1 minuto para inserir apenas . A inserção acima levou 1:19 minutos
Eu quero executar algo parecido com isto para várias consultas:
SELECT COUNT(*) AS COUNT
FROM #TEMP
WHERE AFTER = 'R' AND
DATE >= '2014-01-01' AND
DATE <= '2015-01-01'
É um problema com a inserção mais do que a seleção, mas a temperatura tem muito menos linhas que a tabela original, o que poderia ser melhor do que passar pela tabela várias vezes.
Como posso otimizar isso?
EDITAR
Eu removi o ID de classificação, pensei que o problema estava principalmente no select e não no insert. Foi um palpite.
Não consigo criar um único em nenhum índice, pois não há campos ou linhas exclusivos.
Estou usando o SQL Server 2012.
Informações da tabela : É uma pilha e possui o seguinte uso de espaço:
name rows reserved data index_size unused
mytbl 24869658 9204568 KB 3017952 KB 5816232 KB 370384 KB
SELECT COUNT(*) AS COUNT FROM original_table WHERE AFTER = 'R' AND DATE >= '2014-01-01' AND DATE < '2015-01-01'
, por que você não tenta otimizar cada uma (consulta) separadamente? Você não tem permissão para adicionar índices à tabela?TABLE
eFIELD
da#temp
tabela (afinal, todas as linhas têmTABLE = 'OTB' AND FIELD = 'STATUS'
para a tabela temporária específica).CREATE TABLE
instrução). O voto negativo foi porque a questão não estava clara.Respostas:
A questão é principalmente sobre como otimizar a instrução select:
Removendo as projeções redundantes e adicionando o
dbo
esquema presumido :Sem um índice como o
([TABLE],[FIELD]) INCLUDE ([AFTER],[DATE])
SQL Server, há duas opções principais:[TABLE] = 'OTB'
e[FIELD] = 'STATUS'
(usandoIDX6
) e execute uma pesquisa de heap (RID) por linha para recuperar as colunas[AFTER]
e[DATE]
.Se o otimizador escolhe uma varredura de heap ou procura de índice com pesquisa RID depende da seletividade estimada dos predicados
[TABLE] = 'OTB'
e[FIELD] = 'STATUS'
. Verifique se o número estimado de linhas da busca corresponde à realidade. Caso contrário, atualize suas estatísticas. Teste a consulta com uma dica de tabela que força o uso do índice, se essa condição for razoavelmente seletiva . Se o otimizador estiver atualmente escolhendo a busca de índice, teste o desempenho com umaINDEX(0)
ouFORCESCAN
dica para verificar a pilha.Além disso, você pode melhorar um pouco a varredura da pilha removendo parte do espaço não utilizado (370 MB). No SQL Server 2008, isso pode ser feito reconstruindo a pilha. O espaço não utilizado nos heaps geralmente resulta de exclusões executadas sem que um bloqueio de tabela seja executado (sem um bloqueio de tabela, as páginas vazias não são desalocadas de um heap). As tabelas que apresentam exclusões freqüentes costumam ser melhor armazenadas como uma tabela em cluster por esse motivo.
O desempenho da varredura de heap depende de quanto da tabela está armazenada na memória, quanto deve ser lido do disco, quão cheias as páginas estão, a velocidade do armazenamento persistente, se a varredura é de E / S ou ligada à CPU ( paralelismo pode ajudar).
Se o desempenho ainda for inaceitável após a investigação de todas as opções acima, tente defender um novo índice. Se disponível na sua versão do SQL Server, um possível índice filtrado para a consulta especificada seria:
Considere também a compactação de índice, se disponível e benéfica. Sem um novo índice de algum tipo, há relativamente pouco que você pode fazer para melhorar o desempenho da consulta especificada.
fonte
IDX6 nonclustered located on PRIMARY TABLE, FIELD
. Talvez isso mude as coisas que você mencionou?Eu acho que há um caso para alterar os índices aqui porque:
Esse também seria um bom caso de uso para índices columnstore não agrupados, introduzidos no SQL Server 2012, ou seja, resumir / agregar algumas colunas em uma tabela grande com muitas colunas.
Embora esses índices tenham o efeito colateral de tornar a tabela somente leitura (com exceção da alternância de partição), eles podem transformar o desempenho de consultas agregadas nas condições corretas. O aspecto somente leitura pode ser gerenciado, descartando e recriando o índice ou os dados simples da chave de partição na tabela.
Configurei uma plataforma de teste simples para imitar sua configuração e vi uma boa melhoria no desempenho:
Meus resultados, 6 segundos v 0,08 segundos:
Em resumo, tente criar um caso com seu chefe para que os índices sejam alterados ou, pelo menos, crie algum tipo de processo durante a noite em que esses registros sejam gravados em uma tabela / banco de dados de relatório somente leitura, onde você pode fazer seu trabalho e adicionar indexação apropriado para essa carga de trabalho.
fonte