毫无疑问,文章标题中提出的问题不是新问题,已经提出了不止一次的问题,并已就该问题达成共识““并非真正需要,甚至可能有害”。
但是,最近评论中的讨论使我重新考虑。
随着时间的流逝,任何SSD仍然会强烈碎片化(内部,以FTL形式)...带有线性读取功能的新录制的SSD可以提供较高的速度,但是如果它已经可以工作,它的性能就会低得多,因为它将仅对您有效。
是的,通常不会发生这种情况:要么我们“一点一点”地写入小文件/小块FS元信息(我们并不真正在乎其线性读取速度),要么我们“大量”写入大文件,一切都会好起来的。您也可能会在大型文件中添加一些小块,例如日志,但是它们的生存期相对较短,因此我在这里看不到任何特殊问题。
但是,很容易想象一个非常真实的场景,其中可能会发生SSD的所有相同内部碎片:数据库文件中存在相当活跃的随机记录。随着时间的流逝,它(在操作系统级别保持不打散)在物理上会变得非常零散,这会大大降低seq扫描,备份等的速度。
为了验证,我编写了一个脚本并进行了测试。
破坏者:问题仅出现在所使用的其中一个模型上(严重影响性能)(制造商将其定位为不是数据中心,而是台式机/笔记本电脑)。
这是什么一回事呢?SSD内还有哪些碎片?, SSD . NAND flash ( ) . SSD 512- ( 4096-) , .
- , , FTL (flash translation layer): flash- , ( ) , , - log- .
, , , , — .
, FTL, , , , . , .
.
脚本的想法是:我们创建一个数千兆字节的文件,填充随机数据,测量顺序读取的速度。
接下来,使用随机访问,我们重写测试文件的一部分,并再次测量线性读取的速度。如果我们的猜想是真的,那么现在从文件读取的速度会变慢。
每次写之后,我们要做三个读操作与它们之间的延迟的情况下在后台进行碎片整理的一些驱动器,然后读取速度提高。
, SSD, , - , , . - , , , , , .
TRIM: SSD «», , FTL. NAND flash, . , , . SSD , .
, , , .
, SSD ( linux /dev/urandom
).
.
linux c dash, coreutils fio debian buster, , freebsd «».
echo preparing...
dd if=/dev/urandom of=testfile bs=1M count=4096 status=none
sync
for A in 1 2 3; do
sleep 10
dd if=testfile of=/dev/null bs=1M iflag=direct
done
for A in 50 200 800 4000; do
echo fio: write ${A}M...
fio --name=test1 --filename=testfile --bs=4k --iodepth=1 --numjobs=1 --rw=randwrite --io_size=${A}M --randrepeat=0 --direct=1 --size=4096M > /dev/null
sync
for B in 1 2 3; do
echo sleep ${B}0
sleep ${B}0
dd if=testfile of=/dev/null bs=1M iflag=direct
done
done
echo sleep 3600
sleep 3600
dd if=testfile of=/dev/null bs=1M iflag=direct
, NVMe- intel windows; , stackexchange -
psfio
; exe- .
$testfile = "c:\temp\testfile"
$fio = "c:\temp\fio-3.18-x64\fio"
echo "preparing..."
$filestream = New-Object System.IO.FileStream($testfile, "Create")
$binarywriter = New-Object System.IO.BinaryWriter($filestream)
$out = new-object byte[] 1048576
For ($i=1; $i -le 4096; $i++) {
(new-object Random).NextBytes($out);
$binarywriter.write($out)
}
$binarywriter.Close()
For ($i=1; $i -le 3; $i++) {
sleep 10
$time = Measure-Command {
Invoke-Expression "$fio --name=test1 --filename=$testfile --bs=1M --iodepth=1 --numjobs=1 --rw=read --direct=1 --size=4096M" *>$null
}
$seconds = $time.Minutes*60+$time.Seconds+$time.Milliseconds/1000
echo "read in $seconds"
}
foreach ($A in 50,200,800,4000) {
echo "fio: write ${A}M..."
Invoke-Expression "$fio --name=test1 --filename=$testfile --bs=4k --iodepth=1 --numjobs=1 --rw=randwrite --io_size=${A}M --randrepeat=0 --direct=1 --size=4096M" *>$null
For ($i=10; $i -le 30; $i+=10) {
echo "sleep $i"
sleep $i
$time = Measure-Command {
Invoke-Expression "$fio --name=test1 --filename=$testfile --bs=1M --iodepth=1 --numjobs=1 --rw=read --direct=1 --size=4096M" *>$null
}
$seconds = $time.Minutes*60+$time.Seconds+$time.Milliseconds/1000
echo "read in $seconds"
}
}
rm $testfile
:
- : , «» ( ) , ;
- windows - (, , , );
- ( ) .
( ) 4 :
DC ( — /); SATA, NVMe, , .
, PM981 ( , , ), — 3.5 , SATA .
, , .
: SSD , , , ( intel, , ; samsung , ).
(, - NAND flash).
XG5: , SMART >>150, — 300-400 , flash , SSD.
: mysql 100. , , «» mysql ( 600/), (>2/).
SSD, : , , . , downtime ( - ). , , .
( ) SSD:
sync
fsfreeze -f /mountpoint
dd if=/dev/nvme0n1p2 of=/dev/nvme0n1p2 bs=512M iflag=direct oflag=direct status=progress
fsfreeze -u /mountpoint
«» . - , , , -. «»: 100%, SSD « , TRIM» ( , TRIM, , ).
, « » .
简介:碎片整理对某些 SSD 可能有用,但与HDD 不太一样(一点也不?)。对于我们而言,重要的是,不仅文件位于连续的扇区链中,而且这些扇区中的记录是连续的。
PS:如果读者能在自己的位置运行脚本并为SSD编号,我将不胜感激,因为我选择的驱动器是单面的。