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 / 136733
Accepted
Shelby115
Shelby115
Asked: 2016-04-28 05:33:17 +0800 CST2016-04-28 05:33:17 +0800 CST 2016-04-28 05:33:17 +0800 CST

Quando as colunas computadas são computadas?

  • 772

Quando os valores das colunas computadas são determinados?

  • Quando o valor é recuperado?
  • Quando o valor é alterado?
  • Em alguma outra hora?

Acho que essa é uma pergunta de iniciante, pois não estou encontrando nada em minhas pesquisas.

sql-server computed-column
  • 3 3 respostas
  • 8352 Views

3 respostas

  • Voted
  1. Aaron Bertrand
    2016-04-28T06:33:07+08:002016-04-28T06:33:07+08:00

    Isso é muito fácil de provar por conta própria. Podemos criar uma tabela com uma coluna computada que usa uma função escalar definida pelo usuário e, em seguida, verificar planos e estatísticas de função antes e depois de uma atualização e seleção e ver quando uma execução é registrada.

    Digamos que temos esta função:

    CREATE FUNCTION dbo.mask(@x varchar(32))
    RETURNS varchar(32) WITH SCHEMABINDING
    AS
    BEGIN
      RETURN (SELECT 'XX' + SUBSTRING(@x, 3, LEN(@x)-4) + 'XXXX');
    END
    GO
    

    E esta tabela:

    CREATE TABLE dbo.Floobs
    (
      FloobID int IDENTITY(1,1),
      Name varchar(32),
      MaskedName AS CONVERT(varchar(32), dbo.mask(Name)),
      CONSTRAINT pk_Floobs PRIMARY KEY(FloobID),
      CONSTRAINT ck_Name CHECK (LEN(Name)>=8)
    );
    GO
    

    Vamos verificar sys.dm_exec_function_stats(novidade no SQL Server 2016 e Banco de Dados SQL do Azure) antes e depois de uma inserção e depois de uma seleção:

    SELECT o.name, s.execution_count
    FROM sys.dm_exec_function_stats AS s
    INNER JOIN sys.objects AS o
    ON o.[object_id] = s.[object_id]
    WHERE s.database_id = DB_ID();
    
    INSERT dbo.Floobs(Name) VALUES('FrankieC');
    
    SELECT o.name, s.execution_count
    FROM sys.dm_exec_function_stats AS s
    INNER JOIN sys.objects AS o
    ON o.[object_id] = s.[object_id]
    WHERE s.database_id = DB_ID();
    
    SELECT * FROM dbo.Floobs;
    
    SELECT o.name, s.execution_count
    FROM sys.dm_exec_function_stats AS s
    INNER JOIN sys.objects AS o
    ON o.[object_id] = s.[object_id]
    WHERE s.database_id = DB_ID();
    

    Não vejo nenhuma chamada de função no insert, apenas no select.

    Agora, solte as tabelas e faça novamente, desta vez mudando a coluna para PERSISTED:

    DROP TABLE dbo.Floobs;
    GO
    DROP FUNCTION dbo.mask;
    GO
    
    ...
      MaskedName AS CONVERT(varchar(32), dbo.mask(Name)) PERSISTED,
    ...
    

    E vejo o contrário acontecendo: recebo uma execução logada no insert, mas não no select.

    Não tem uma versão moderna o suficiente do SQL Server para usar sys.dm_exec_function_stats? Não se preocupe, isso também é capturado nos planos de execução .

    Para a versão não persistente, podemos ver a função referenciada apenas no select:

    insira a descrição da imagem aqui

    insira a descrição da imagem aqui

    Enquanto a versão persistida mostra apenas o cálculo acontecendo na inserção:

    insira a descrição da imagem aqui

    insira a descrição da imagem aqui

    Agora, Martin traz um grande ponto em um comentário : isso nem sempre será verdade. Vamos criar um índice que não cubra a coluna computada persistente e executar uma consulta que usa esse índice e ver se a pesquisa obtém os dados dos dados persistentes existentes ou calcula os dados em tempo de execução (solte e recrie a função e tabela aqui):

    CREATE INDEX x ON dbo.Floobs(Name);
    GO
    
    INSERT dbo.Floobs(name) 
      SELECT LEFT(name, 32) 
      FROM sys.all_columns 
      WHERE LEN(name) >= 8;
    

    Agora, vamos executar uma consulta que usa o índice (na verdade ele usa o índice por padrão neste caso específico de qualquer maneira, mesmo sem uma cláusula where):

    SELECT * FROM dbo.Floobs WITH (INDEX(x))
      WHERE Name LIKE 'S%';
    

    Vejo execuções adicionais nas estatísticas da função e o plano não mente:

    insira a descrição da imagem aqui

    Então, a resposta é DEPENDE . Nesse caso, o SQL Server achou que seria mais barato recalcular os valores do que realizar pesquisas. Isso pode mudar devido a uma variedade de fatores, portanto, não confie nisso. E isso pode acontecer em qualquer direção, seja ou não uma função definida pelo usuário; Eu só o usei aqui porque tornou muito mais fácil ilustrar.

    • 34
  2. Best Answer
    Arthur D
    2016-04-28T05:53:11+08:002016-04-28T05:53:11+08:00

    Depende de como você define a coluna calculada. Uma PERSISTEDcoluna computada será calculada e então armazenada como dados dentro da tabela. Se você não definir a coluna como PERSISTED, ela será calculada quando sua consulta for executada.

    Por favor, veja a resposta de Aaron para uma ótima explicação e prova.

    Pinal Dave também descreve isso em detalhes e mostra provas de armazenamento em sua série:

    SQL SERVER – Coluna Calculada – PERSISTIDO e Armazenamento

    • 19
  3. Corpulent Brony
    2018-02-24T10:22:53+08:002018-02-24T10:22:53+08:00

    A resposta a esta pergunta é verdadeiramente "depende". Acabei de encontrar um exemplo em que o SQL Server está usando o índice na coluna computada persistente, mas ainda está executando a função, como se os valores nunca tivessem persistido para começar. Pode ter a ver com o tipo de dados da coluna ( nvarchar(37)) ou possivelmente com o tamanho da tabela (cerca de 7 milhões de linhas), mas o SQL Server decidiu ignorar a persistedpalavra-chave, ao que parece, nesta instância específica.

    Nesse caso, a chave primária na tabela é TransactionID, que também é uma coluna computada e persistente. O plano de execução está gerando uma varredura de índice e em uma tabela com apenas 7 milhões de linhas, essa consulta simples está levando mais de 2 a 3 minutos para ser executada porque a função é executada novamente em cada linha e os valores não parecem ser persistentes em o índice.

    criando tabela com coluna persistente plano de execução mostrando que a função está sendo executada

    • -1

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