首页 > 数据库 >PostgreSQL 从开发要换PG表字段的 collaion 说起 到 程序员别异想天开了

PostgreSQL 从开发要换PG表字段的 collaion 说起 到 程序员别异想天开了

时间:2023-06-22 13:04:56浏览次数:35  
标签:字符 要换 PostgreSQL encoding UTF8 collaion PG collation pg


PostgreSQL  从开发要换PG表字段的 collaion 说起 到 程序员别异想天开了_java

2021年绝对是一个有意思的念头,估计过10年都会想到今年的一些变革,很多人都会被影响,改变,重新开始,或寻找新的路径。

归正题,新公司的开发小朋友,对DB 提出了一个问题,就是要修改某个表的字段的collation,究其原因为了某些业务中这个字段的排序。然后我就告诉DB,NO NO NO ,究其原因曾经SQL SERVER 更换collation后产生的问题还在记忆里面。不过PG的collation  说起来还真没有怎么研究,空白要被填补,否则不能一致倚老卖老。

首先要确认几点,

1   PG 要更换collation 针对表的字段,主要就是文本的类型 char ,varchar, text. 

2   collation 与PG的 encoding 有关,于创建数据库INSTANCE 初始化有关,与建库时的建库语句有关,也与建表的语句有关。

3     网上我是没有找到中文关于这类的问题清晰的描述或文章,我就当开个头。

从PG的encoding 说起,PG 的encoding 分为 server encoding 和 client encoding 

通过下面的语句,我们可以找到当前数据库的关于encoding, collation 的信息

SELECT d.datname as "Name",
       pg_catalog.pg_get_userbyid(d.datdba) as "Owner",
       pg_catalog.pg_encoding_to_char(d.encoding) as "Encoding",
       d.datcollate as "Collate",
       d.datctype as "Ctype",
       pg_catalog.array_to_string(d.datacl, E'\n') AS "Access privileges"
FROM pg_catalog.pg_database d
ORDER BY 1;

PostgreSQL  从开发要换PG表字段的 collaion 说起 到 程序员别异想天开了_python_02

数据库的encoding 是UTF8 ,客户的client encoding 也是UTF8

PostgreSQL  从开发要换PG表字段的 collaion 说起 到 程序员别异想天开了_大数据_03

问题1  我的client_encoding 和 server_encoding 可以不一样吗?

我们来看看下面的操作,将客户端的encoding 变为 BIG5码, 则在键入一些字符,系统会直接报错,无法确认这些字符是什么。

PostgreSQL  从开发要换PG表字段的 collaion 说起 到 程序员别异想天开了_数据库_04

而将客户端的encoding 更换为 GBK,我们在查询俄文,也不会报错

PostgreSQL  从开发要换PG表字段的 collaion 说起 到 程序员别异想天开了_大数据_05

这就涉及到PG 本身支持的字符编码类型,这里台湾省的BIG5码不在支持范围(以PG13为例),中国的GBK属于PG的扩展标准。  下方是一个表,这个表里面server ICU 为NO 的是 PG 目前不支持的字符编码。

而UTF8 为什么为一个大多数PG的字符的标准,因为这个编码是 ALL,也就是通吃各种字符以及国别的语言。

PostgreSQL  从开发要换PG表字段的 collaion 说起 到 程序员别异想天开了_大数据_06

而这些是怎么带入到我们的建库语句中,参见下图, create database encoding 以及 LC_COLLATE, LC_CTYPE 这三个选项。

PostgreSQL  从开发要换PG表字段的 collaion 说起 到 程序员别异想天开了_大数据_07

en-coding 是字符的编码集,此数据库下的所有的默认表的设置,以及字段的编码都为UTF8 , lc_collate 为本地化字符排序规则,lc_ctype 为字符集中的字符分类,这里统计了一下关于UTF8的类型的字符分类,在PG14中有262个。

PostgreSQL  从开发要换PG表字段的 collaion 说起 到 程序员别异想天开了_python_08

我们创建一个使用collate 为 zh_CN的数据库,对比 en_US的数据库又什么不同

PostgreSQL  从开发要换PG表字段的 collaion 说起 到 程序员别异想天开了_数据库_09

我们在两个数据库中的同样的表,中插入同样的数据,然后order by 一下

en utf8

PostgreSQL  从开发要换PG表字段的 collaion 说起 到 程序员别异想天开了_mysql_10

zh utf8

PostgreSQL  从开发要换PG表字段的 collaion 说起 到 程序员别异想天开了_python_11

那么此时差距就有了,同样都是一样的字符,在排序后,同样都使用UTF8 ,而在collate 不同的情况下, 默认的name  进行排序后的结果就不一致了。

那么怎么能让两个表的order by 的结果一致。

ALTER TABLE test ALTER COLUMN name SET DATA TYPE character varying(255) COLLATE "en_US";

PostgreSQL  从开发要换PG表字段的 collaion 说起 到 程序员别异想天开了_python_12

通过修改表的字段的collation后,再次进行order by ,两个表的结果一致了。

说到这里,回到上面的问题,开发要改字段的collation,为什么没有让他改。

原因

1   不确认修改的字段是否会引起索引的重建的问题

2   修改后,部分查询会出现无法进行的情况

PostgreSQL  从开发要换PG表字段的 collaion 说起 到 程序员别异想天开了_python_13

PostgreSQL  从开发要换PG表字段的 collaion 说起 到 程序员别异想天开了_python_14

上面两个图是字段的collation 是一致的情况下,可以查询出数据(下面的图),如果我修改了某个表的collation ,则查询直接报错。

2021-09-02 01:18:51.116 EDT [48166] ERROR:  could not determine which collation to use for string hashing
2021-09-02 01:18:51.116 EDT [48166] HINT:  Use the COLLATE clause to set the collation explicitly.
2021-09-02 01:18:51.116 EDT [48166] STATEMENT:  select t.id  from test as t inner join test_2 as t2 on t.name = t2.name order by t.name;
ERROR:  could not determine which collation to use for string hashing
HINT:  Use the COLLATE clause to set the collation explicitly.
test_zh=#

主要的原因还是表join 的情况下,使用到了hash 算法,而人类看上去明明一样的两个表的 两个字段,在你修改了collation后,那就彻彻底底的不一样了。

到此为止,还应该深入,但想睡觉了,不过很想和那个程序员说, 您还是别异想天开了,我们应该有其他的方法解决你的需求。

PostgreSQL  从开发要换PG表字段的 collaion 说起 到 程序员别异想天开了_java_15

标签:字符,要换,PostgreSQL,encoding,UTF8,collaion,PG,collation,pg
From: https://blog.51cto.com/u_14150796/6534676

相关文章

  • PostgreSQL autovacuum 5 怎么监控(autovacuum 扫描表工作的百分比)
    PostgreSQL最大的问题就是vacuum,只要PG的实现多版本和UNDO的方式不改变,那么这个话题就会一直继续,到永远。前面四期讲了autovacuum的触发条件,源代码,怎么调整参数,优化,今天最后一章,的说说怎么进行监控,并且评定你的autovacuum的工作是合格的。下面的内容主要是基于几点来围绕的 监......
  • PostgreSQL REPMGR “靠谱”的高可用方式
    REPMGR是一种方便简单的适合企业使用的高可用方式,为什么选择REPMGR作为单体PG的高可用方式1 REPMGR是这三种里面最简单的高可用的方式,这里的意思是结构节点,搭建简单,处理简单2 在网络有波动的情况下,比较好控制,如果遇到网络上的短暂的问题,REPMGR通过一系列的方式可以避免......
  • POSTGRESQL 事务控制(一) (写着费力,看着费劲系列)
    最近发现一个问题, 最近写的关于感性的文字如 DBA职业迷茫何去何从,和另外一篇都是较高的用户读取量,而反观到技术性的文字,基本上都不太高,能到400以上就属于"上帝帮助"了原因我是明白的, 大众化的东西受众必然很多,反而纯技术性的文字实撰写困难,首先自己要理解,然后在......
  • PostgreSQL 怎么通过命令来恢复删除的数据
    最近一段工作较忙,更新的速度可能会减慢,敬请见谅,后期采用隔天更新的方式误删除数据的情况,一般都是通过备份,或日志来进行恢复,当然ORACLEFLASHBACK的模式实际上也是对一定期限的数据进行数据的恢复。 对于POSTGRESQL是否可以进行这样的操作,根据POSTGRESQL的原理来说是可以的。下面......
  • POSTGRESQL 15 pg_basebackup 新功能,LOCAL backup 与 数据强力压缩
    与MYSQL不一样,开源XTRABACKUP的备份软件无法跟上MYSQL版本的更迭,PG这点做的是一贯的好。从来没有让人失望过。所以POSTGRESQL数据的备份一直就不是一个问题,众多的工具以及pg_basebackup良好的功能,让POSTGRESQL备份起来速度与硬件有关。但基于POSTGRESQL本身的原理,数据库表......
  • POSTGRESQL 提高POSTGRESQL性能的一些习惯 (1)
    PostgreSQL是一个很有意思的数据库,在使用中有一些习惯可以在同等的硬件下,更加有效的使用硬件提供的资源,让管理和使用POSTGRESQL获得更多的性能。下面就说说一些使用POSTGRESQL的习惯。1 是否需要降低文件的数量POSTGRESQL的文件很多,这里指的文件的数量,主要指两方面的的文件,数......
  • POSTGRESQL VS MYSQL 到底那个数据库 RDS 技术含量高 ?
    以下内容纯属个人看法云数据库的RDS产品,在传统开源的系列里面大致可以选择的是POSTGRESQL和MYSQL两种,诚然在RDS的里面大部分产品最终的选择还是MYSQL,今天不想讨论产品的量,而是想讨论以下产品的难度,RDS产品在POSTGRESQL和MYSQL两种产品的难度问题。先说结果,POSTGRESQL......
  • Postgresql 如何降低 wal 占用磁盘空间,降低磁盘存储成本
    POSTGRESQLWAL的存储一直是一个值得讨论的问题,到底一个POSTGRESQL在极端的情况下,可以用多少的空间来存储WAL日志。这里不是要讨论逻辑复制槽,也不是讨论ARCHIVE,这里要讨论是一种极端的方法,尝试将POSTGRESQLWAL占用的磁盘空间最小化。这里主要针对的对象是,单机的POSTGRESQL,不......
  • POSTGRESQL 存储过程--如何写出新版本PG的存储过程的小案例
    随着问问题的同学越来越多,公众号内部私信回答问题已经很困难了,所以建立了一个群,关于各种数据库的问题都可以,目前主要是POSTGRESQL,MYSQL,MONGODB,POLARDB,REDIS,SQLSERVER等,期待你的加入,最近在开始研究POSTGRESQL的存储过程,主要的原因有以下几个1因为要开发适合目前公司中......
  • POSTGRESQL 提高POSTGRESQL性能的一些习惯 (3)
    随着问问题的同学越来越多,公众号内部私信回答问题已经很困难了,所以建立了一个群,关于各种数据库的问题都可以,目前主要是POSTGRESQL,MYSQL,MONGODB,POLARDB,REDIS,SQLSERVER等,期待你的加入这个系列写到第三期了,实际上POSTGRESQL的优化和一个核心之一,这就是VACUUM,一个弄不清vac......