【问题标题】:Performance cost of proper utf-8 encoding in PHPPHP 中正确 utf-8 编码的性能成本
【发布时间】:2025-12-10 06:30:01
【问题描述】:

在处理传入数据时,我没有找到绝对最佳的做法。其他一些线程有有用的信息,但我仍然有很多未回答的问题。我只知道 UTF-8 是唯一的现代标准。我的问题涉及到 php 的使用,但也许有一些一般用途可以适用于其他语言。我愿意尊重公认的标准,假设性能成本可以忽略不计。 随意指出基准以证明某些特定选择的合理性。

1) 你真的应该检查每一个传入的数据(apis、get、post、...),受到操纵或存储的影响吗?在 websocket 和 Rest API 的特殊情况下,我看不出这是明智的表现......对每个传入数据和变量进行常量编码字符串检查,这真的应该为良好实践做些什么吗? 如果是,任何在服务器资源上不太昂贵的方法? 我已经看到这被用来确定变量是否为 UTF-8 :

if(preg_match('!!u', $data))
{
   echo 'this is utf-8'; //use the var
}
else 
{
   echo 'definitely not utf-8'; //do something else
}

一直这样做感觉有点矫枉过正。那个函数不应该是mb_ereg_match吗?

2)假设您应该总是检查传入的数据,为了将数据转换为 UTF-8 使用什么可行的函数?

3) 从数据库或 get/post 中获取的日期、整数、小数怎么样...它们与 UTF-8 有什么关系吗,你必须将它们编码成将它们发送到mysql之前的UTF-8? 至于换行符,它们是在 utf-8 中“出现”为可见的换行符,还是在 utf-8 文本中总是显示为 \r\n?在这种情况下,phpMyAdmin 是否有理由将\r\n 替换为界面中的可见换行符?

4) 对数组(尤其是那些要编码成 json 的数组)有同样的问题:

  • 是否应该将数组键编码为 utf-8?
  • 是否应该将密钥中的数据编码为 utf-8?
  • 是否应将所有变量数组本身编码为 utf-8?

5) 我们是否应该学会使用多字节版本的字符串函数来代替通常的非多字节字符串函数,如http://php.net/manual/en/ref.mbstring.php 所示?这意味着获取所有类型的代码,并替换函数以便于重用......

6) 当在 mysql 列上使用utf8mb4_unicode(或它的变体)时,VARCHAR() 可能的最大大小是多少?显然 255 不是一个选项。当字段是索引的一部分时,我也对性能保持警惕。

7) 始终考虑到足够好的性能以应用最佳实践,您能否确认(或纠正)以下是在 php/mysql 环境中处理编码的正确方法,或者如果缺少一个元素;没有列出始终与软件保持最新状态,因为这是常识。

  • Mysql:默认使用utf8mb4_unicode_520_ci 作为排序规则,并且每列可以包含除数字、日期或时间以外的任何内容。
  • 网页:默认使用<meta charset="UTF-8">
  • PHP 服务器:使用扩展名mbstring 并启用其多字节支持参数。 default_charset=UTF-8 在 php.ini 中。
  • PHP 脚本:在每个 .php 页面上使用mb_internal_encoding('UTF-8');,后跟mb_http_output('UTF-8');,在php标签<?php之后的最开始处。 (这不能在 php 中设置为默认值吗?)
  • PDO:在创建新的 PDO 对象时使用参数charset=utf8mb4
  • 文本编辑器:如果使用 Notepad++,从一开始就使用“Encode in UTF-8”参数,适用于每个页面,无论扩展名如何。

希望这个线程是最后一个也是最全面的地方,可以在 php/sql 环境中以可接受的性能了解最佳编码实践。

【问题讨论】:

    标签: php mysql encoding utf-8 utf8mb4


    【解决方案1】:

    我要说的一切次要到:UTF-8 all the way through

    1. 您应该始终事先知道输入的编码,无论是通过遵循上述内容,还是因为您已经向外部数据提供者提供了标准,或者从外部数据提供者那里获得了标准。猜测编码是个坏主意,因此尝试检测编码也是如此。这包括使用像 mb_detect_encoding() 这样的函数,因为没有好的方法来实际检测编码,而且归根结底,这充其量是有根据的猜测。

    2. mb_convert_encoding() 指定了输入和输出编码,因为 #1。

    3. 如果你的输入是一个字符串,你应该按照上面的方法处理它。如果它是一个数字,它或多或少是普遍的。这有一些极端情况,但任何人都不太可能遇到它们而不会陷入更深的麻烦。

    4. 数组是一种复杂类型,如果没有某种形式的中间编码,则无法在系统之间传输,而该编码的规则将定义如何处理字符串数据以及数据本身的字符串编码。例如:Read the JSON spec

    5. 是的。如果您使用的是多字节编码,您应该在适用的情况下使用多字节函数。

    6. IIRC 这取决于页面大小和列中数据的整体大小,因为它们都需要适合单个页面。您可以使用 TEXT 类型来伪造这一点,因为它们在技术上存储在页面外,但它们有自己的权衡。这本身就是一个完整的问题,可能在其他地方得到了回答。

    7. UTF-8 all the way through

    【讨论】: