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 / 94887
Accepted
Gregoire D.
Gregoire D.
Asked: 2015-03-11 07:33:54 +0800 CST2015-03-11 07:33:54 +0800 CST 2015-03-11 07:33:54 +0800 CST

Qual é o impacto do LC_CTYPE em um banco de dados PostgreSQL?

  • 772

Então, eu tenho poucos servidores Debian com PostgreSQL nele. Historicamente, esses servidores e o PostgreSQL são localizados com o conjunto de caracteres Latin 9 e naquela época estava tudo bem. Agora temos que lidar com coisas como polonês, grego ou chinês, então mudá-lo se tornou um problema crescente.

Quando tentei criar um banco de dados UTF8, recebi a mensagem:

ERRO: a codificação UTF8 não corresponde à localidade fr_FR Detalhe: A configuração LC_CTYPE escolhida requer a codificação LATIN9.

Poucas vezes fiz uma pesquisa sobre o assunto com meu velho amigo Google, e tudo que encontrei foram alguns procedimentos supercomplicados como atualizar o Debian LANG, recompilar o PostgreSQL com o charset correto, editar todas as LC_variáveis ​​do sistema e outras soluções obscuras. Então, por enquanto, deixamos essa questão de lado.

Recentemente, voltou novamente, os gregos querem as coisas e o latim 9 não quer. E enquanto eu estava analisando essa questão novamente, um colega veio até mim e disse: “Não, é fácil, olhe”.

Ele não editou nada, não fez truques de mágica, ele apenas fez esta consulta SQL:

CREATE DATABASE my_utf8_db
  WITH ENCODING='UTF8'
       OWNER=admin
       TEMPLATE=template0
       LC_COLLATE='C'
       LC_CTYPE='C'
       CONNECTION LIMIT=-1
       TABLESPACE=pg_default;

E funcionou bem.

Na verdade, eu não sabia LC_CTYPE='C'e fiquei surpreso que usar isso não estivesse nas primeiras soluções do Google e até mesmo no Stack Overflow. Olhei em volta e só encontrei uma menção na documentação do PostgreSQL.

Quando LC_CTYPE é C ou POSIX, qualquer conjunto de caracteres é permitido, mas para outras configurações de LC_CTYPE existe apenas um conjunto de caracteres que funcionará corretamente. Como a configuração LC_CTYPE é congelada pelo initdb, a aparente flexibilidade para usar diferentes codificações em diferentes bancos de dados de um cluster é mais teórica do que real, exceto quando você seleciona a localidade C ou POSIX (desativando assim qualquer reconhecimento de localidade real).

Então isso me fez pensar, isso é muito fácil, muito perfeito, quais são as desvantagens? E eu tenho dificuldade em encontrar uma resposta ainda. Então vou postar aqui:

tl; dr: Quais são as desvantagens de usar LC_CTYPE='C'em uma localização específica? É ruim fazer isso? O que devo esperar para quebrar?

postgresql collation
  • 2 2 respostas
  • 27433 Views

2 respostas

  • Voted
  1. Best Answer
    Daniel Vérité
    2015-03-12T06:20:16+08:002015-03-12T06:20:16+08:00

    Quais são as desvantagens de usar LC_CTYPE='C' em uma localização específica

    A documentação menciona a relação entre localidades e recursos SQL no Locale Support :

    As configurações de localidade influenciam os seguintes recursos SQL:

    • Classifique a ordem nas consultas usando ORDER BY ou os operadores de comparação padrão em dados textuais

    • As funções superior, inferior e initcap

    • Operadores de correspondência de padrões (expressões regulares no estilo LIKE, SIMILAR TO e POSIX); localidades afetam tanto a correspondência que não diferencia maiúsculas de minúsculas quanto a classificação de caracteres por expressões regulares de classe de caractere

    • A família de funções to_char

    • A capacidade de usar índices com cláusulas LIKE

    O primeiro item (ordem de classificação) é sobre LC_COLLATEe os outros parecem ser sobre LC_CTYPE.

    LC_COLLATE

    LC_COLLATEafeta comparações entre strings. Na prática, o efeito mais visível é a ordem de classificação. LC_COLLATE='C'(ou POSIXque é um sinônimo) significa que é a ordem dos bytes que conduz as comparações, enquanto uma localidade no language_REGIONformulário significa que as regras culturais irão conduzir as comparações.

    Um exemplo com nomes em francês, executados de dentro de um banco de dados UTF-8:

    select firstname from (values ('bernard'), ('bérénice'), ('béatrice'), ('boris'))
     AS l(firstname)
    order by firstname collate "fr_FR";
    

    Resultado:

    primeiro nome
    -----------
     Beatriz
     berenice
     Bernardo
     boris
    

    béatricevem antes borisde , porque o E acentuado se compara com O como se não fosse acentuado. É uma regra cultural.

    Isso difere do que acontece com uma Clocalidade:

    select firstname from (values ('bernard'), ('bérénice'), ('béatrice'), ('boris')) 
     AS l(firstname)
    order by firstname collate "C";
    

    Resultado:

    primeiro nome
    -----------
     Bernardo
     boris
     Beatriz
     berenice
    
    

    Agora os nomes com E acentuado são colocados no final da lista. A representação de byte éem UTF-8 é o hexadecimal C3 A9e para oele é 6f. c3é maior do que 6fisso na Clocalidade, 'béatrice' > 'boris'.

    Não são apenas acentos. Existem regras mais complexas com hifenização, pontuação e caracteres estranhos como œ. Regras culturais estranhas são esperadas em cada localidade.

    Agora, se as strings a serem comparadas misturam idiomas diferentes, como quando se tem uma firstnamecoluna para pessoas de todo o mundo, pode ser que qualquer localidade em particular não deva dominar, de qualquer maneira, porque alfabetos diferentes para idiomas diferentes não foram projetados para serem ordenados uns contra os outros.

    Neste caso Cé uma escolha racional, e tem a vantagem de ser mais rápida, pois nada supera comparações de bytes puros.

    LC_CTYPE

    Definir LC_CTYPEcomo 'C' implica que C funciona como isupper(c)ou tolower(c)fornece resultados esperados apenas para caracteres no intervalo US-ASCII (ou seja, até o ponto de código 0x7F em Unicode).

    Como as funções SQL como upper(), lower()ou initcap são implementadas no Postgres em cima dessas funções libc, elas são afetadas por isso assim que houver caracteres não US-ASCII nas strings.

    Exemplo:

    test=> show lc_ctype;
      lc_ctype   
    -------------
     fr_FR.UTF-8
    (1 row)
    
    -- Good result
    test=> select initcap('élysée');
     initcap 
    ---------
     Élysée
    (1 row)
    
    -- Wrong result
    -- collate "C" is the same as if the db has been created with lc_ctype='C'
    test=> select initcap('élysée' collate "C");
     initcap 
    ---------
     éLyséE
    (1 row)
    

    Para a Clocalidade, éé tratado como um caractere não categorizável.

    Da mesma forma, resultados errados também são obtidos com expressões regulares:

    test=> select 'élysée' ~ '^\w+$';
     ?column? 
    ----------
     t
    (1 row)
    
    test=> select 'élysée' COLLATE "C" ~ '^\w+$';
     ?column? 
    ----------
     f
    (1 row)
    
    • 44
  2. cafecoder905
    2016-03-10T06:19:28+08:002016-03-10T06:19:28+08:00

    Em referência à resposta aceita de Daniel sobre classificação usando agrupamentos, esteja ciente de que, se você estiver executando o PostgreSQL em um Mac, seu agrupamento preferido pode não funcionar como esperado devido a configurações inadequadas para alguns agrupamentos no nível do sistema operacional. Você pode ler mais sobre o assunto aqui:

    http://www.postgresql.org/message-id/[email protected]

    Este não é um problema específico do PostgreSQL, especificamente, mas sim um problema com a configuração padrão do Mac para configurações de agrupamento. Meu sistema atual está executando o PostgreSQL 9.3 no OS X El Capitan versão 10.11 e sofre com esse problema. Meu sistema retorna os mesmos resultados de consulta, independentemente de eu usar o agrupamento “fr_FR” ou “en_US”. Por exemplo:

    Usando o agrupamento “fr_FR”:

    select firstname from (values ('bernard'), ('bérénice'), ('béatrice'), ('boris'))
    AS l(firstname)
    order by firstname collate "fr_FR";
    
    results:
    ==============
    bernard
    boris
    béatrice
    bérénice
    

    Usando o agrupamento “en_US”:

    select firstname from (values ('bernard'), ('bérénice'), ('béatrice'), ('boris'))
    AS l(firstname)
    order by firstname collate "en_US";
    
    results:
    ==============
    bernard
    boris
    béatrice
    bérénice
    

    No meu sistema, as configurações de agrupamento (no nível do sistema operacional) são as mesmas para “fr_FR” e “en_US”, conforme demonstrado no shell executando diff:

    cd /usr/share/locale
    diff fr_FR.UTF-8/LC_COLLATE en_US.UTF-8/LC_COLLATE
    

    Espero que esta informação adicional seja útil para quem está lendo isso e está usando o PostgreSQL em um Mac que sofre desse problema.

    • 11

relate perguntas

  • Posso ativar o PITR depois que o banco de dados foi usado

  • Práticas recomendadas para executar a replicação atrasada do deslocamento de tempo

  • Os procedimentos armazenados impedem a injeção de SQL?

  • Sequências Biológicas do UniProt no PostgreSQL

  • Qual é a diferença entre a replicação do PostgreSQL 9.0 e o Slony-I?

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