MySQL COMPRESS vs PHP gzcompress

时间:2014-07-07 09:40:22

标签: php mysql performance compression

正在开发一个PHP应用程序,其中需要将大量文本存储在MySQL数据库中。已经遇到了PHP的gzcompress和MySQL的COMPRESS函数作为减少存储数据大小的可能方法。

有人可以建议走哪条路吗?

(我目前的想法是gzcompress似乎更灵活,因为它允许指定压缩级别,而COMPRESS可能更容易实现和更好的解耦?性能也是一个重要的考虑因素。)

6 个答案:

答案 0 :(得分:9)

这两种方法或多或少是相同的,实际上你可以混合它们:在php中压缩并在MySQL中解压缩,反之亦然。

在MySQL中压缩:

INSERT INTO table (data) VALUE(COMPRESS(data));

在PHP中压缩:

$compressed_data = "\x1f\x8b\x08\x00".gzcompress($uncompressed_data);

在MySQL中解压缩:

SELECT UNCOMPRESS(data) FROM table;

在PHP中解压缩:

$uncompressed_data = gzuncompress(substr($compressed_data, 4));

另一种选择是use MySQL table compression

它只需要配置,然后它是透明的。

答案 1 :(得分:7)

这可能是一个老问题,但它作为Google搜索目的地很重要。 MySQL的COMPRESS()与PHP的gzcompress()的结果是相同的EXCEPT,MySQL在数据上放置一个4字节的标头,表示未压缩的数据长度。您可以轻松忽略MySQL的COMPRESS()中的前4个字节并将其提供给gzuncompress()并且它可以正常工作,但是您无法获取PHP的gzcompress()的结果并使用MySQL的UNCOMPRESS(),除非您特别小心添加4字节长度的标头,这当然需要已经有未压缩的数据......

答案 2 :(得分:4)

接受的答案不使用正确的4字节标题。
前4个字节是LENGTH而不是静态标头 我不知道使用错误长度的影响,但它不会很好,并且有可能在将来崩溃数据库或表格内容(如果不是现在)

POC示例的正确答案: 输出mysql:

mysql : "select hex(compress('1234512345'))"
0A000000789C3334323631350411000AEB01FF

php等价物:

$string="1234512345";
$data=gzcompress($string);
$len=mb_strlen($string);
$head=pack('V',$len);

echo($head);
echo($data);

PHP的输出:

php test.php  | hexdump -C
00000000  0a 00 00 00 78 9c 33 34  32 36 31 35 04 11 00 0a

答案 3 :(得分:2)

他们都使用zlib,因此压缩可能大致相同。测试一下,看看。

答案 4 :(得分:1)

Johns answer 几乎是正确的。必须使用 strlen 而不是 mb_strlen 来计算长度,因为后者会将多字节字符识别为“1 个字符”,尽管它们跨越多个字节。以下面的示例为例,其中包含 3 个字节的“▄”字符:


$string="▄";
$compressed = gzcompress($string, 6);

echo "with strlen\n";
$len  = strlen($string);
$head = pack('V', $len);
$base64 = base64_encode($head.$compressed);

echo "Length of string: $len\n";
echo $base64."\n";
echo `mysql -e "SELECT UNCOMPRESS(FROM_BASE64('$base64'))" -u root -proot -h mysql`;


echo "\n\nwith mb_strlen\n";
$len  = mb_strlen($string);
$head = pack('V', $len);
$base64 = base64_encode($head.$compressed);

echo "Length of string: $len\n";
echo $base64."\n";
echo `mysql -e "SELECT UNCOMPRESS(FROM_BASE64('$base64'))" -u root -proot -h mysql`;

输出:

with strlen
Length of string: 3
AwAAAHicezStBQAEWQH9
UNCOMPRESS(FROM_BASE64('AwAAAHicezStBQAEWQH9'))
▄


with mb_strlen
Length of string: 1
AQAAAHicezStBQAEWQH9
UNCOMPRESS(FROM_BASE64('AQAAAHicezStBQAEWQH9'))
NULL

答案 5 :(得分:0)

添加此答案以供参考,因为我需要使用uncompress()对数据进行解压缩,其中解压缩后的大小存储在blob的单独列中。

根据前面的答案,uncompress()期望压缩数据的前4个字节为长度,以小尾数格式存储。可以使用concat例如

select uncompress(
    concat(
        char(size & 0x000000ff),
        char((size & 0x0000ff00) >> 8),
        char((size & 0x00ff0000) >> 16),
        char((size & 0xff000000) >> 24),
    compressed_data)) as decompressed
from my_blobs;