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 / 140381
Accepted
Paul White
Paul White
Asked: 2016-06-04 22:35:05 +0800 CST2016-06-04 22:35:05 +0800 CST 2016-06-04 22:35:05 +0800 CST

Existe algum benefício em SCHEMABINDING uma função além da proteção de Halloween?

  • 772

É bem conhecido que SCHEMABINDINGuma função pode evitar um spool desnecessário nos planos de atualização:

Se você estiver usando UDFs T-SQL simples que não tocam em nenhuma tabela (ou seja, não acessam dados), certifique-se de especificar a SCHEMABINDINGopção durante a criação das UDFs. Isso tornará os UDFs vinculados ao esquema e garantirá que o otimizador de consulta não gere nenhum operador de spool desnecessário para planos de consulta envolvendo esses UDFs.

Existem outras vantagens de SCHEMABINDINGuma função, mesmo que ela não acesse dados?

sql-server functions
  • 1 1 respostas
  • 10298 Views

1 respostas

  • Voted
  1. Best Answer
    Paul White
    2016-06-04T22:35:05+08:002016-06-04T22:35:05+08:00

    Sim.

    Deixar de especificar WITH SCHEMABINDINGsignifica que o SQL Server ignora as verificações detalhadas que normalmente faz no corpo da função. Ele simplesmente marca a função como acessando dados (conforme mencionado no link fornecido na pergunta).

    Esta é uma otimização de desempenho. Se não fizesse essa suposição, o SQL Server teria que realizar as verificações detalhadas em cada chamada de função (uma vez que a função não vinculada poderia mudar a qualquer momento).

    Existem cinco propriedades de funções importantes:

    • Determinismo
    • Precisão
    • Acesso de dados
    • Acesso a dados do sistema
    • Verificação do sistema

    Por exemplo, considere a seguinte função escalar não vinculada:

    CREATE FUNCTION dbo.F
    (
        @i integer
    )
    RETURNS datetime
    AS
    BEGIN
        RETURN '19000101';
    END;
    

    Podemos olhar para as cinco propriedades usando uma função de metadados:

    SELECT 
        IsDeterministic = OBJECTPROPERTYEX(Func.ID, 'IsDeterministic'),
        IsPrecise = OBJECTPROPERTYEX(Func.ID, 'IsPrecise'),
        IsSystemVerified = OBJECTPROPERTYEX(Func.ID, 'IsSystemVerified'),
        UserDataAccess = OBJECTPROPERTYEX(Func.ID, 'UserDataAccess'),
        SystemDataAccess = OBJECTPROPERTYEX(Func.ID, 'SystemDataAccess')
    FROM (VALUES(OBJECT_ID(N'dbo.F', N'FN'))) AS Func (ID);
    

    Resultado

    As duas propriedades de acesso a dados foram definidas como true e as outras três foram definidas como false .

    Isso tem implicações além das esperadas (uso em exibições indexadas ou colunas computadas indexadas, por exemplo).

    Efeitos no otimizador de consulta

    A propriedade Determinism em particular afeta o otimizador de consulta. Possui regras detalhadas sobre os tipos de reescritas e manipulações que pode realizar, e estas são muito restritas para elementos não determinísticos. Os efeitos colaterais podem ser bastante sutis.

    Por exemplo, considere as duas tabelas a seguir:

    CREATE TABLE dbo.T1
    (
        SomeInteger integer PRIMARY KEY
    );
    GO
    CREATE TABLE dbo.T2
    (
        SomeDate datetime PRIMARY KEY
    );
    

    ...e uma consulta que usa a função (conforme definido anteriormente):

    SELECT * 
    FROM dbo.T1 AS T1
    JOIN dbo.T2 AS T2
        ON T2.SomeDate = dbo.F(T1.SomeInteger);
    

    O plano de consulta é o esperado, apresentando uma busca na tabela T2:

    Buscar plano

    No entanto, se a mesma consulta lógica for escrita usando uma tabela derivada ou uma expressão de tabela comum:

    WITH CTE AS
    (
        SELECT *, dt = dbo.F(T1.SomeInteger) 
        FROM dbo.T1 AS T1
    )
    SELECT * 
    FROM CTE
    JOIN dbo.T2 AS T2
        ON T2.SomeDate = CTE.dt;
    
    -- Derived table
    SELECT
        *
    FROM 
    (
        SELECT *, dt = dbo.F(T1.SomeInteger)
        FROM dbo.T1 AS T1
    ) AS T1
    JOIN dbo.T2 AS T2
        ON T2.SomeDate = T1.dt;
    

    O plano de execução agora apresenta um scan, com o predicado envolvendo a função preso em um Filter:

    plano de digitalização

    Isso também acontece se a tabela derivada ou a expressão de tabela comum for substituída por uma exibição ou função em linha. Uma FORCESEEKdica (e outras tentativas semelhantes) não terá sucesso:

    Mensagem de erro

    A questão fundamental é que o otimizador de consulta não pode reordenar elementos de consulta não determinísticos tão livremente .

    Para produzir uma busca, o predicado Filtro precisaria ser movido para baixo no plano para o acesso aos dados T2. Este movimento é impedido quando a função não é determinística.

    Fixar

    A correção para este exemplo envolve duas etapas:

    1. AdicionarWITH SCHEMABINDING
    2. Torne a função determinística

    O primeiro passo é trivial. A segunda envolve a remoção da conversão implícita não determinística de string para datetime; substituindo-o por um determinístico CONVERT. Nenhum dos dois é suficiente por si só .

    ALTER FUNCTION dbo.F
    (
        @i integer
    )
    RETURNS datetime
    WITH SCHEMABINDING
    AS
    BEGIN
        -- Convert with a deterministic style
        RETURN CONVERT(datetime, '19000101', 112);
    END;
    

    As propriedades da função agora são:

    Novas propriedades

    Com o otimizador liberado, todos os exemplos agora produzem o plano de busca desejado .


    Observe que usar um CASTto datetimena função não funcionaria, pois não é possível especificar um estilo de conversão nessa sintaxe:

    ALTER FUNCTION dbo.F
    (
        @i integer
    )
    RETURNS datetime
    WITH SCHEMABINDING
    AS
    BEGIN
        -- Convert with a deterministic style
        RETURN CAST('19000101' AS datetime);
    END;
    

    Esta definição de função produz o plano de varredura e as propriedades mostram que ele permanece não determinístico:

    Propriedades da função CAST

    • 92

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