正在开发一个PHP应用程序,其中需要将大量文本存储在MySQL数据库中。已经遇到了PHP的gzcompress
和MySQL的COMPRESS
函数作为减少存储数据大小的可能方法。
有人可以建议走哪条路吗?
(我目前的想法是gzcompress
似乎更灵活,因为它允许指定压缩级别,而COMPRESS
可能更容易实现和更好的解耦?性能也是一个重要的考虑因素。)
答案 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;