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 / 238518
Accepted
Joe Obbish
Joe Obbish
Asked: 2019-05-20 14:16:13 +0800 CST2019-05-20 14:16:13 +0800 CST 2019-05-20 14:16:13 +0800 CST

É seguro usar Strings em vez de SqlStrings para parâmetros de entrada da função CLR?

  • 772

Eu tenho um UDF escalar CLR implementado por meio de código C#. Percebi que usar o Stringtipo de dados para parâmetros de entrada melhora significativamente o desempenho em comparação com o SqlStringtipo de dados. Em Stairway to SQLCLR Level 5: Development (Usando .NET no SQL Server) , Solomon Rutzky menciona os seguintes motivos para preferir os tipos de dados SQL para strings:

A principal diferença entre os tipos de dados CLR (Common Language Runtime) nativos e os tipos de dados do SQL Server é que os primeiros não permitem valores NULL, enquanto os últimos fornecem semântica NULL completa.

...

Os valores de streaming podem ser obtidos via SqlChars para N[VAR]CHAR, SqlBytes para [VAR]BINARY e SqlXml.CreateReader() para XML...

...

Ao usar SqlString (não string ou mesmo SqlChars) você pode acessar as propriedades CompareInfo, CultureInfo, LCID e SqlCompareOptions...

Eu sei que minha entrada nunca será NULL, não preciso transmitir os valores e nunca verificarei as propriedades de agrupamento. Meu caso poderia ser uma exceção em que é melhor usar Stringem vez de SqlString? Se eu for com essa abordagem, há algo em particular que eu deva observar?

Se for importante, estou usando o agrupamento padrão do SQL Server. Aqui está parte do meu código-fonte, s1sendo o parâmetro de entrada:

fixed (char* chptr = s1)
{
    char* cp = (char*)current;

    for (int i = 0; i < s1.Length; i++)
    {
        cp[i] = chptr[i];
    }
}
sql-server sql-server-2017
  • 1 1 respostas
  • 577 Views

1 respostas

  • Voted
  1. Best Answer
    Solomon Rutzky
    2019-05-20T23:58:42+08:002019-05-20T23:58:42+08:00

    Excelente pergunta. Até onde eu sei, nessas condições (ou seja, sem garantias NULLe sem necessidade de funcionalidade extra), não deve haver nenhuma preocupação específica. Esta poderia ser uma situação semelhante a CURSORs onde, se uma regra genérica for necessária, seria: "não use cursores". Mas, a regra atual é: "só use cursores quando/onde apropriado". O problema é educar as pessoas sobre os detalhes técnicos dos cursores para que possam tomar essa decisão, ou seja, aqueles de nós que sabem o suficiente sobre essas coisas ignoram a regra genérica e passam a usá-los adequadamente.

    Então, eu aconselho as pessoas a "sempre" usar os Sql*tipos porque isso reduz a confusão e os erros. Mas, isso não quer dizer que usar stringem sua situação não seria melhor. Eu digo vá em frente, e se você tiver algum problema com string, é fácil voltar e mudar para SqlString.

    Com relação ao agrupamento e sua declaração de:

    Se for importante, estou usando o agrupamento padrão do SQL Server.

    Embora geralmente não importe, também não está claro o que você quer dizer aqui, pois não há um agrupamento padrão verdadeiro. É provável que você esteja se referindo ao infeliz agrupamento padrão ao instalar o SQL Server em um sistema operacional com uma configuração de idioma "inglês americano" (ou seja, LCID = 1033), que é SQL_Latin1_General_CP1_CI_AS. Mas ainda há três níveis de agrupamentos que podem ser todos diferentes (Instância/Servidor, Banco de Dados e Coluna), e você pode estar significando apenas um ou até dois desses níveis.

    A razão pela qual menciono tudo isso é que há algumas coisas não óbvias acontecendo aqui:

    1. até certo ponto, nenhum desses 3 níveis que os agrupamentos afetam é relevante, pois a cultura padrão dos threads SQLCLR é a configuração de idioma no nível do sistema operacional (o LCID do idioma selecionado). Isso afeta as operações usando String.Equalsao usar um dos dois StringComparison.CurrentCulture*valores e as operações usando String.Compareao não especificar uma cultura.

    2. até certo ponto, nenhum desses 3 níveis que os agrupamentos afetam é relevante, pois o =operador faz uma comparação ordinal (ou seja, deve ser o mesmo que usar um _BIN2agrupamento). É assim também que String.CompareOrdinalfunciona, assim como String.Equalsquando não passa StringComparison.CurrentCulture*ou StringComparison.InvariantCulture*valores.

    3. uma instância em que o agrupamento do SQL Server é importante é ao concatenar um SqlStringparâmetro de entrada com um stringvia +. Nesse caso, o +operador cria um new SqlStringpara conter o valor de stringpara que possa concatenar os dois SqlStrings. O problema é que o novo SqlStringé criado com os threads atuais LCID (que é o LCID do Sistema Operacional), e então o +operador compara os dois SqlStringss antes da concatenação (ou seja, verifica se eles são do "mesmo tipo"). Mas, devido ao SqlStringparâmetro de entrada ter o LCID do banco de dados (não instância ou coluna) e o parâmetro criado implicitamenteSqlStringtendo um LCID do sistema operacional, a operação obtém uma exceção informando que os "agrupamentos" não correspondem. Legal, hein?

      Isso, no entanto, não deve ser um problema, pois ninguém deve usar o SqlStringvalor diretamente ao desejar a string. Em vez disso, todos devem sempre usar a Valuepropriedade para obter a string.


    Dito isto, estou curioso para saber qual teste você fez para determinar que stringfoi mais rápido. Testei uma UDF simples que aceita um único NVARCHAR(4000)parâmetro de entrada, concatena uma string curta e depois retorna o novo valor. Uma versão dessa UDF aceita e retorna string, e a outra versão aceita e retorna SqlString. Mais de 1 milhão de iterações, a stringversão foi cerca de 200-300 milissegundos mais rápida do que a SqlStringversão, cerca de 50% do tempo, ao comparar seus tempos mais rápidos (em todas as 1 milhão de iterações, não por cada). Nos outros 50% do tempo, o ganho de desempenho foi de cerca de 100 milissegundos, mas também pode ser nenhum.

    Além disso, em relação ao seu código de teste: é s1sempre o parâmetro de entrada direta, seja stringou SqlString? Se sim, você também deve testar a criação de uma string localmente e defini-la s1.Value. Significado:

    string s2 = s1.Value; // when s1 is SqlString instead of string
    
    fixed (char* chptr = s2)
    {
        char* cp = (char*)current;
    
        for (int i = 0; i < s2.Length; i++)
        {
            cp[i] = chptr[i];
        }
    }
    

    Além disso, algumas outras opções para possivelmente testar:

    1. Método SqlString.GetUnicodeBytes (retorna byte[])
    2. Propriedade SqlChars.Value (retorna char[])
    • 8

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