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 / 126632
Accepted
Artashes  Khachatryan
Artashes Khachatryan
Asked: 2016-01-20 05:48:20 +0800 CST2016-01-20 05:48:20 +0800 CST 2016-01-20 05:48:20 +0800 CST

Aviso sobre conversão implícita

  • 772

Eu tenho uma tabela com 2 colunas de nome:

CREATE TABLE Test
(
  TestID int identity primary key clustered
  , Name_Eng nvarchar(50)
  , Name_Nat nvarchar(50)
)

Agora preciso de uma query para pegar essa Namecoluna separada por ,, assim:

    DECLARE @NameColumns NVARCHAR(1024)

            SET @NameColumns = STUFF(
      (SELECT   ',' + 'Test.' + name AS [text()]
       FROM     ( SELECT    c.name
                  FROM      sys.columns c 
                            INNER JOIN sys.tables t ON t.object_id = c.object_id
                  WHERE     t.name = 'Test'
                            AND c.name LIKE 'Name_%'
                ) AS D
                FOR                  XML PATH('') ,
                                         TYPE).value('.[1]', 'VARCHAR(MAX)'), 1, 1,
                                     N'')

select  @NameColumns

Mas esta consulta tem um aviso no plano de execução:

aviso de conversão implícita

Existe alguma maneira de remover esse aviso?

sql-server performance
  • 3 3 respostas
  • 3749 Views

3 respostas

  • Voted
  1. Best Answer
    Mikael Eriksson
    2016-01-20T13:02:45+08:002016-01-20T13:02:45+08:00

    O aviso existe por causa da função XML value(). O segundo parâmetro value()é o que você deseja que o valor armazenado no XML seja convertido. Você poderia argumentar que esta não é de fato uma conversão implícita, mas uma conversão muito explícita, já que você está pedindo que isso aconteça. Talvez algo para um item de conexão sugerir à Microsoft.

    Maneira mais simples de reproduzir o que você vê.

    declare @X xml;
    select @X.value('text()[1]', 'int');
    

    Dá esses dois avisos.

    <Warnings>
        <PlanAffectingConvert ConvertIssue="Cardinality Estimate" Expression="CONVERT_IMPLICIT(int,XML Reader with XPath filter.[lvalue],0)" />
        <PlanAffectingConvert ConvertIssue="Cardinality Estimate" Expression="CONVERT_IMPLICIT(int,XML Reader with XPath filter.[value],0)" />
    </Warnings>
    

    Como você pode ver, você também obtém int's e obtém dois deles para cada invocação de value().

    declare @X xml;
    select @X.value('text()[1]', 'int'),
           @X.value('text()[1]', 'bit');
    
    <Warnings>
        <PlanAffectingConvert ConvertIssue="Cardinality Estimate" Expression="CONVERT_IMPLICIT(int,XML Reader with XPath filter.[lvalue],0)" />
        <PlanAffectingConvert ConvertIssue="Cardinality Estimate" Expression="CONVERT_IMPLICIT(int,XML Reader with XPath filter.[value],0)" />
        <PlanAffectingConvert ConvertIssue="Cardinality Estimate" Expression="CONVERT_IMPLICIT(bit,XML Reader with XPath filter.[lvalue],0)" />
        <PlanAffectingConvert ConvertIssue="Cardinality Estimate" Expression="CONVERT_IMPLICIT(bit,XML Reader with XPath filter.[value],0)" />
    </Warnings>
    

    A conversão é feita no operador Stream Aggregate que calcula o valor desta forma.

    MIN(CASE WHEN [@X] IS NULL 
          THEN NULL 
          ELSE 
          CASE WHEN datalength(XML Reader with XPath filter.[value])>=(128) 
            THEN CONVERT_IMPLICIT(int,XML Reader with XPath filter.[lvalue],0) 
            ELSE CONVERT_IMPLICIT(int,XML Reader with XPath filter.[value],0) 
          END 
        END)
    

    O resultado da função Table Valued é retornado na coluna lvalueou . valueA expressão verifica usando datalengthpara descobrir de onde deve ser buscada e, em seguida, converte-a no tipo de dados desejado.

    Existe alguma maneira de remover esse aviso?

    Sim existe. Você remove a TYPEdiretiva da FOR XML PATHinstrução e remove a chamada para a value()função. Um efeito colateral de fazer isso é que os valores que você concatena que contêm caracteres que precisam ser codificados no XML como &<>serão codificados em seu resultado.

    • 10
  2. Aaron Bertrand
    2016-01-20T07:50:14+08:002016-01-20T07:50:14+08:00

    Embora eu concorde com @Kin sobre os tipos de dados, não acho que esse aviso seja tão problemático quanto você pensa. Você está executando a concatenação agrupada, que será muito mais cara do que qualquer conversão de qualquer maneira (e, como disse Daniel, a menos que suas visualizações de catálogo sejam massivas - como em maior que a memória física - é improvável que afete qualquer coisa em termos de estimativa também).

    Eu escreveria a consulta dessa maneira, tomando cuidado para nunca usar strings varchar (o que também significa parar de deixar de fora o Nprefixo em strings literais) e também garantir que você use terminadores de instrução :

    DECLARE @NameColumns nvarchar(max); -- why 1024 when you use max below?
    
    SET @NameColumns = STUFF(
      (SELECT   N',Test.' + name AS [text()] FROM    
        (
          SELECT c.name FROM sys.columns AS c 
            INNER JOIN sys.tables AS t 
              ON t.object_id = c.object_id
            WHERE t.name = N'Test'
            AND   c.name LIKE N'Name_%'
        ) AS D FOR XML PATH(N''),
        TYPE).value(N'.[1]', N'nvarchar(max)'), 1, 1, N'');
    
    SELECT @NameColumns;
    

    Mesmo assim, não acredito que haja alguma maneira de evitar a conversão implícita sem alterar a saída evitando TYPE/ value()como Mikael sugeriu . Eu diria que se preocupe com isso quando você puder provar que isso tem algum impacto material no desempenho da consulta. Em meus testes, as duas formas diferentes tiveram o mesmo desempenho (estamos falando de sub-10ms todas as vezes), mas é claro que se eu tiver uma tabela nomeada Sales & Stuff, ela ficará Sales &amp; Stuffsem a conversão implícita.

    • 9
  3. Daniel Hutmacher
    2016-01-20T06:15:18+08:002016-01-20T06:15:18+08:00

    O aviso no plano de consulta significa que, como você tem uma conversão implícita de tipo de dados, o SQL Server não poderá adivinhar com precisão o número correto de linhas retornadas, o que, por sua vez, pode levar a um plano abaixo do ideal.

    Isso é importante em consultas que precisam ter um bom desempenho, normalmente porque trabalham com muitos dados, mas na sua situação, não parece ser o caso, pois você está apenas consultando sys.tablese sys.columns.

    A resposta curta para sua pergunta é: não importa, a menos que você tenha milhões e milhões de tabelas e colunas em seu banco de dados.

    • 3

relate perguntas

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

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

  • Onde posso encontrar o log lento do mysql?

  • Como posso otimizar um mysqldump de um banco de dados grande?

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