AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / dba / Perguntas / 249182
Accepted
Randi Vertongen
Randi Vertongen
Asked: 2019-09-20 06:08:27 +0800 CST2019-09-20 06:08:27 +0800 CST 2019-09-20 06:08:27 +0800 CST

Colunas esparsas, tempo de CPU e índices filtrados

  • 772

Pouca

Ao fazer alguns testes em colunas esparsas, como você faz, houve um revés de desempenho que eu gostaria de saber a causa direta.

DDL

Criei duas tabelas idênticas, uma com 4 colunas esparsas e outra sem colunas esparsas.

--Non Sparse columns table & NC index
CREATE TABLE dbo.nonsparse( ID INT IDENTITY(1,1) PRIMARY KEY NOT NULL,
                      charval char(20) NULL,
                      varcharval varchar(20) NULL,
                      intval int NULL,
                      bigintval bigint NULL
                      );
CREATE INDEX IX_Nonsparse_intval_varcharval
ON dbo.nonsparse(intval,varcharval)
INCLUDE(bigintval,charval);

-- sparse columns table & NC index

CREATE TABLE dbo.sparse( ID INT IDENTITY(1,1) PRIMARY KEY NOT NULL,
                      charval char(20) SPARSE NULL ,
                      varcharval varchar(20) SPARSE NULL,
                      intval int SPARSE NULL,
                      bigintval bigint SPARSE NULL
                      );

CREATE INDEX IX_sparse_intval_varcharval
ON dbo.sparse(intval,varcharval)
INCLUDE(bigintval,charval);

DML

Em seguida, inseri cerca de 2540 valores NON-NULL em ambos.

INSERT INTO dbo.nonsparse WITH(TABLOCK) (charval, varcharval,intval,bigintval)
SELECT 'Val1','Val2',20,19
FROM MASTER..spt_values;

INSERT INTO dbo.sparse WITH(TABLOCK) (charval, varcharval,intval,bigintval)
SELECT 'Val1','Val2',20,19
FROM MASTER..spt_values;

Depois, inseri 1M valores NULL em ambas as tabelas

INSERT INTO dbo.nonsparse WITH(TABLOCK)  (charval, varcharval,intval,bigintval)
SELECT TOP(1000000) NULL,NULL,NULL,NULL 
FROM MASTER..spt_values spt1
CROSS APPLY MASTER..spt_values spt2;

INSERT INTO dbo.sparse WITH(TABLOCK) (charval, varcharval,intval,bigintval)
SELECT TOP(1000000) NULL,NULL,NULL,NULL 
FROM MASTER..spt_values spt1
CROSS APPLY MASTER..spt_values spt2;

Consultas

Execução de tabela não esparsa

Ao executar esta consulta duas vezes na tabela não esparsa recém-criada:

SET STATISTICS IO, TIME ON;
SELECT  * FROM dbo.nonsparse
WHERE   1= (SELECT 1) -- force non trivial plan
OPTION(RECOMPILE,MAXDOP 1);

As leituras lógicas mostram 5257 páginas

(1002540 rows affected)
Table 'nonsparse'. Scan count 1, logical reads 5257, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

E o tempo de CPU é de 343 ms

 SQL Server Execution Times:
   CPU time = 343 ms,  elapsed time = 3850 ms.

execução de tabela esparsa

Executando a mesma consulta duas vezes na tabela esparsa:

SELECT  * FROM dbo.sparse
WHERE   1= (SELECT 1) -- force non trivial plan
OPTION(RECOMPILE,MAXDOP 1);

As leituras são mais baixas, 1763

(1002540 rows affected)
Table 'sparse'. Scan count 1, logical reads 1763, physical reads 3, read-ahead reads 1759, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

Mas o tempo de CPU é maior, 547 ms .

 SQL Server Execution Times:
   CPU time = 547 ms,  elapsed time = 2406 ms.

Plano de execução de tabela esparsa

plano de execução de tabela não esparsa


Perguntas

Pergunta original

Como os valores NULL não são armazenados diretamente nas colunas esparsas, o aumento no tempo de CPU pode ser devido ao retorno dos valores NULL como um conjunto de resultados? Ou é simplesmente o comportamento observado na documentação ?

Colunas esparsas reduzem os requisitos de espaço para valores nulos ao custo de mais sobrecarga para recuperar valores não nulos

Ou a sobrecarga está relacionada apenas às leituras e armazenamento usado?

Mesmo executando ssms com a opção de descarte de resultados após execução, o tempo de cpu da seleção esparsa foi maior (407 ms) em comparação com a não esparsa (219 ms).

EDITAR

Pode ter sido a sobrecarga dos valores não nulos, mesmo que haja apenas 2540 presentes, mas ainda não estou convencido.

Isso parece ser o mesmo desempenho, mas o fator esparso foi perdido.

CREATE INDEX IX_Filtered
ON dbo.sparse(charval,varcharval,intval,bigintval)
WHERE charval IS NULL  
      AND varcharval IS NULL
      AND intval  IS NULL
      AND bigintval  IS NULL;

CREATE INDEX IX_Filtered
ON dbo.nonsparse(charval,varcharval,intval,bigintval)
WHERE charval IS NULL  
      AND varcharval IS NULL
      AND intval  IS NULL
      AND bigintval  IS NULL;


    SET STATISTICS IO, TIME ON;

SELECT  charval,varcharval,intval,bigintval FROM dbo.sparse WITH(INDEX(IX_Filtered))
WHERE charval IS NULL AND  varcharval IS NULL
                     AND intval  IS NULL
                     AND bigintval  IS NULL
                     OPTION(RECOMPILE,MAXDOP 1);


SELECT  charval,varcharval,intval,bigintval 
FROM dbo.nonsparse WITH(INDEX(IX_Filtered))
WHERE charval IS NULL AND 
                      varcharval IS NULL
                     AND intval  IS NULL
                     AND bigintval  IS NULL
                     OPTION(RECOMPILE,MAXDOP 1);

Parece ter aproximadamente o mesmo tempo de execução:

 SQL Server Execution Times:
   CPU time = 297 ms,  elapsed time = 292 ms.

 SQL Server Execution Times:
   CPU time = 281 ms,  elapsed time = 319 ms.

Mas por que as leituras lógicas são a mesma quantidade agora? O índice filtrado para a coluna esparsa não deveria armazenar nada, exceto o campo de ID incluído e algumas outras páginas que não são de dados?

Table 'sparse'. Scan count 1, logical reads 5785,
Table 'nonsparse'. Scan count 1, logical reads 5785

E o tamanho de ambos os índices:

RowCounts   Used_MB Unused_MB   Total_MB
1000000     45.20   0.06        45.26

Por que são do mesmo tamanho? A escassez foi perdida?

Ambos os planos de consulta ao usar o índice filtrado


Informação extra

select @@version

Microsoft SQL Server 2017 (RTM-CU16) (KB4508218) - 14.0.3223.3 (X64) 12 de julho de 2019 17:43:08 Copyright (C) 2017 Microsoft Corporation Developer Edition (64 bits) no Windows Server 2012 R2 Datacenter 6.3 (Build 9600: ) (Hipervisor)

Ao executar as consultas e selecionar apenas o campo ID , o tempo de CPU é comparável, com leituras lógicas mais baixas para a tabela esparsa.

Tamanho das mesas

SchemaName  TableName   RowCounts   Used_MB Unused_MB   Total_MB
dbo         nonsparse   1002540     89.54   0.10        89.64
dbo         sparse      1002540     27.95   0.20        28.14

Ao forçar o índice clusterizado ou não clusterizado, a diferença de tempo da CPU permanece.

sql-server sql-server-2017
  • 1 1 respostas
  • 418 Views

1 respostas

  • Voted
  1. Best Answer
    Josh Darnell
    2019-09-20T09:35:29+08:002019-09-20T09:35:29+08:00

    Ou é simplesmente o comportamento observado na documentação?

    Parece que sim. A "sobrecarga" mencionada na documentação parece ser a sobrecarga da CPU.

    Perfilando as duas consultas, a consulta esparsa amostrava 367 ms de CPU, enquanto a não esparsa tinha 284 ms de CPU. Isso é uma diferença de 83 ms.

    captura de tela do Perfview mostrando CPU total para thread que executou a consulta

    Onde está a maior parte disso?

    Ambos os perfis parecem muito semelhantes até chegarem ao sqlmin!IndexDataSetSession::GetNextRowValuesInternal. Nesse ponto, o código esparso segue um caminho que executa sqlmin!IndexDataSetSession::GetDataLong, que chama algumas funções que parecem estar relacionadas ao recurso de coluna esparsa ( HasSparseVector, StoreColumnValue) e somam (42 + 11 =) 53 ms.

    captura de tela da diferença de CPU para coluna esparsa

    Por que são do mesmo tamanho? A escassez foi perdida?

    Sim, parece que a otimização de armazenamento esparso não é transferida para índices não clusterizados quando a coluna esparsa é usada como chave de índice. Portanto, as colunas de chave de índice não clusterizadas ocupam seu tamanho total, independentemente da dispersão, mas as colunas incluídas ocupam zero espaço se forem esparsas e NULL.

    Observando a DBCC PAGEsaída de uma página de índice clusterizado com colunas esparsas com valor NULL, posso ver que o comprimento do registro é 11 (4 para o ID + 7 para a sobrecarga padrão por registro):

    Record Type = PRIMARY_RECORD        Record Attributes =  NULL_BITMAP    Record Size = 11
    

    Para o índice filtrado, o registro é sempre 40, que é a soma do tamanho de todas as colunas de chave (4 byte ID + 20 byte charval + 4 byte varcharval + 4 byte intval + 8 byte big intval = 40 bytes).

    Por algum motivo, DBCC PAGEnão inclui a sobrecarga de 7 bytes em "Tamanho do registro" para registros de índice:

    Record Type = INDEX_RECORD          Record Attributes =  NULL_BITMAP    Record Size = 40
    

    O tamanho do índice não filtrado é menor (ID de 4 bytes + intval de 4 bytes + varcharval de 4 bytes = 12 bytes) porque duas das colunas esparsas são colunas incluídas, o que novamente obtém a otimização de esparsidade:

    Record Type = INDEX_RECORD          Record Attributes =  NULL_BITMAP    Record Size = 12
    

    Acho que essa diferença de comportamento se alinha com uma das limitações listadas na página de documentos:

    Uma coluna esparsa não pode fazer parte de um índice clusterizado ou de um índice de chave primária exclusivo

    Eles podem ser chaves em índices não clusterizados, mas não são armazenados esparsamente.

    • 7

relate perguntas

  • SQL Server - Como as páginas de dados são armazenadas ao usar um índice clusterizado

  • Preciso de índices separados para cada tipo de consulta ou um índice de várias colunas funcionará?

  • Quando devo usar uma restrição exclusiva em vez de um índice exclusivo?

  • Quais são as principais causas de deadlocks e podem ser evitadas?

  • Como determinar se um Índice é necessário ou necessário

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host

    • 12 respostas
  • Marko Smith

    Como fazer a saída do sqlplus aparecer em uma linha?

    • 3 respostas
  • Marko Smith

    Selecione qual tem data máxima ou data mais recente

    • 3 respostas
  • Marko Smith

    Como faço para listar todos os esquemas no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    Como usar o sqlplus para se conectar a um banco de dados Oracle localizado em outro host sem modificar meu próprio tnsnames.ora

    • 4 respostas
  • Marko Smith

    Como você mysqldump tabela (s) específica (s)?

    • 4 respostas
  • Marko Smith

    Listar os privilégios do banco de dados usando o psql

    • 10 respostas
  • Marko Smith

    Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Como faço para listar todos os bancos de dados e tabelas usando o psql?

    • 7 respostas
  • Martin Hope
    Jin conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane Como faço para listar todos os esquemas no PostgreSQL? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh Por que o log de transações continua crescendo ou fica sem espaço? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland Listar todas as colunas de uma tabela especificada 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney O MySQL pode realizar consultas razoavelmente em bilhões de linhas? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx Como posso monitorar o andamento de uma importação de um arquivo .sql grande? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas Como posso cronometrar consultas SQL usando psql? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas Como faço para listar todos os bancos de dados e tabelas usando o psql? 2011-02-18 00:45:49 +0800 CST

Hot tag

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve