Server 2012R2 (and up) has a technology called "Storage Tiers". Basically this is the software equivalent of a hybrid-SSD, you have a mixture of SSDs and HDDs in the same storage space, frequently used data is kept on the SSDs, with less accessed data on the HDDs. Theoretically this gets you the benefits of the speed of an SSD with the cheap space of an HDD. Now this is normally only interesting to admins working with servers with lots of disks, but it turns out that, even though there's no indication in the GUI, all of the functionality is still part of Windows 10. The only problem is we have to do everything via PowerShell. The following is a write up/how to guide from me puzzling out how to make it work. I've been running a tiered mirror volume for a few months now, and it works like you'd expect. I'm posting this because I've only seen one other person document it, and hopefully this gets indexed by some search engines. You will need: Some knowledge of PowerShell, and ideally of the Storage Spaces cmdlets. You'll have to run all of these commands from an elevated command prompt, which gives you all the access rights you need to delete all your own data, so be careful eh? At least two SSDs At least two HDDs Go right ahead and plug your empty harddrives and SSDs in. I already had three HDDs in a Storage Pool, so this will deal only with adding the SSDs. Plug in your SSDs (oh, and make sure you've backed up any data you care about) In disk management, (attempt to) delete any existing partitions and make sure the new SSDs have a GPT partition table Code: Get-PhysicalDisk FriendlyName SerialNumber CanPool OperationalStatus HealthStatus Usage Size ------------ ------------ ------- ----------------- ------------ ----- ---- KINGSTON SV300S37A60G AAAAAAAAA False OK Healthy Auto-Select 55.9 GB ST4000VN000-1H4168 AAAAAAAAA False OK Healthy Auto-Select 3.64 TB TOSHIBA DT01ACA200 AAAAAAAAA False OK Healthy Auto-Select 1.82 TB ST2000DM001-9YN164 AAAAAAAAA False OK Healthy Auto-Select 1.82 TB Samsung SSD 840 EVO 250GB AAAAAAAAA False OK Healthy Auto-Select 232.89 GB KINGSTON SV300S37A60G AAAAAAAAA False OK Healthy Auto-Select 55.9 GB TOSHIBA External USB 3.0 AAAAAAAAA False OK Healthy Auto-Select 3.64 TB SAMSUNG MZVLW512HMJP-00000 AAAAAAAAA False OK Healthy Auto-Select 476.94 GB There's our two drives, handily both have the same name. If they had different FriendlyNames, or the same as another disk that we didn't want to mess with, this would be more complicated. (and yes, I've blanked the serials) Code: Get-PhysicalDisk -FriendlyName "KINGSTON SV300S37A60G" FriendlyName SerialNumber CanPool OperationalStatus HealthStatus Usage Size ------------ ------------ ------- ----------------- ------------ ----- ---- KINGSTON SV300S37A60G AAAAAAAAAAAAAAAA False OK Healthy Auto-Select 55.9 GB KINGSTON SV300S37A60G AAAAAAAAAAAAAAAA False OK Healthy Auto-Select 55.9 GB CanPool is false why? Fortunately there is a way of finding out Code: Get-PhysicalDisk -FriendlyName "KINGSTON SV300S37A60G" | Format-Table FriendlyName,OperationalStatus,Size,MediaType,CannotPoolReason FriendlyName OperationalStatus Size MediaType CannotPoolReason ------------ ----------------- ---- --------- ---------------- KINGSTON SV300S37A60G OK 60022480896 SSD Insufficient Capacity KINGSTON SV300S37A60G OK 60022480896 SSD Insufficient Capacity (we could have piped the command to fl, aka Format-List, which shows you all the data Get-PhysicalDisk has, and this is what I actually did first, but it produces too much output to paste without making this even longer, so we Format-Table instead and only ask for a few columns. I'll use the short form of ft from now on) Insufficient Capacity? wtf? Turns out that there was still a partition table or something on the disk, so, we need to reset it. ***warning, this is where you have to start being careful, otherwise you'll wipe a perfectly good harddrive*** Reset our two SSDs. Note, I can get away with referring to them by name because I only care about these two drives. Code: Reset-PhysicalDisk -FriendlyName "KINGSTON SV300S37A60G" Did it work? Code: Get-PhysicalDisk -FriendlyName "KINGSTON SV300S37A60G" | ft FriendlyName SerialNumber CanPool OperationalStatus HealthStatus Usage Size ------------ ------------ ------- ----------------- ------------ ----- ---- KINGSTON SV300S37A60G AAAAAAAAAAAAAAAA True OK Healthy Auto-Select 55.9 GB KINGSTON SV300S37A60G AAAAAAAAAAAAAAAA True OK Healthy Auto-Select 55.9 GB yay! Code: Add-PhysicalDisk -PhysicalDisks $SSDs -StoragePoolFriendlyName "Storage Pool" (Yes, my main storage pool is called "Storage Pool", imaginative eh?) See if it worked Code: Get-StoragePool "Storage Pool" | Get-PhysicalDisk | ft FriendlyName,OperationalStatus,HealthStatus,Size,MediaType FriendlyName OperationalStatus HealthStatus Size MediaType ------------ ----------------- ------------ ---- --------- KINGSTON SV300S37A60G OK Healthy 59861106688 SSD ST4000VN000-1H4168 OK Healthy 4000762036224 HDD TOSHIBA DT01ACA200 OK Healthy 2000381018112 HDD ST2000DM001-9YN164 OK Healthy 2000381018112 HDD KINGSTON SV300S37A60G OK Healthy 59861106688 SSD More yay! (They're also showing up in the GUI as well) Now time to add tiering: Code: New-StorageTier -StoragePoolFriendlyName "Storage Pool" -FriendlyName SSD_Tier -MediaType SSD New-StorageTier -StoragePoolFriendlyName "Storage Pool" -FriendlyName HDD_Tier -MediaType HDD Check what we have: Code: Get-StorageTier | ft FriendlyName,MediaType,PhysicalDiskRedundancy,ResiliencySettingName,Interleave FriendlyName MediaType PhysicalDiskRedundancy ResiliencySettingName Interleave ------------ --------- ---------------------- --------------------- ---------- SSD_Tier SSD 1 Mirror 262144 HDD_Tier HDD 1 Mirror 262144 So each storage tier is limited to what kind of virtual disk you can create; Mirror, Parity and so on. Now, I've only got two SSDs so Mirror is the best I can do with them as part of a virtual disk, but I've got three HDDs and I'd like to be able to use them for a parity space, with some write caching, so I need a third storage tier set up for parity. It turns out I can have multiple tiers using the same drives: Code: New-StorageTier -StoragePoolFriendlyName "Storage Pool" -FriendlyName HDD_Parity_Tier -MediaType HDD -ResiliencySettingName Parity And now we have three: Code: Get-StorageTier | ft FriendlyName,MediaType,PhysicalDiskRedundancy,ResiliencySettingName,Interleave FriendlyName MediaType PhysicalDiskRedundancy ResiliencySettingName Interleave ------------ --------- ---------------------- --------------------- ---------- SSD_Tier SSD 1 Mirror 262144 HDD_Tier HDD 1 Mirror 262144 HDD_Parity_Tier HDD 1 Parity 262144 Right, lets create a mirrored space, with storage tiers. Hmm, I want 1TB for now, and I don't want to use all the SSDs, so I think 955GB on the harddrives, and 45 on the SSDs. This is the only downside of storage tiers as they stand right now, you have to specify up front how big you want the disk, and you can't expand it later. Much easier working with short variables, so I'm going to specify the two tiers I want to work with right now: Code: $ssd_tier = Get-StorageTier -FriendlyName "SSD_Tier" $hdd_tier = Get-StorageTier -FriendlyName "HDD_Tier" Right, now the moment of truth: Code: New-VirtualDisk -StoragePoolFriendlyName "Storage Pool" -FriendlyName "Tierd-Mirror" -StorageTiers @($ssd_tier, $hdd_tier) -StorageTierSizes @(45GB, 955GB) -ResiliencySettingName Mirror -WriteCacheSize 1GB (took me a few goes before it worked, because I specified 55GB of SSD and 3955GB of HDD, neither of which is available, I am an idiot) Lets see if it worked: Code: Get-VirtualDisk | ft FriendlyName,HealthStatus,ResiliencySettingName,ProvisioningType,AllocatedSize FriendlyName HealthStatus ResiliencySettingName ProvisioningType AllocatedSize ------------ ------------ --------------------- ---------------- ------------- Vid Healthy Parity Thin 348429221888 Tierd-Mirror Healthy 1073741824000 Mirror Healthy Mirror Thin 330980917248 Hmm, resiliency setting is blank, I'm sure that'll be fine... And now it's showing up in the GUI, just need to format it from there. And now to check it's doing what it should. To force Windows to optimise the storage (ie to move the commonly accessed data to the SSDs), we use good old defrag Code: defrag m: /g /h /# Microsoft Drive Optimizer Copyright (c) Microsoft Corp. Invoking tier optimization on Mirror (M:)... The operation completed successfully. Post Defragmentation Report: Volume Information: Volume size = 999.81 GB Free space = 649.21 GB Storage Tier Optimization Report: % I/Os Serviced from Perf Tier Perf Tier Size Required 100% 18.31 MB * 95% 17.37 MB 90% 16.43 MB 85% 15.56 MB 80% 14.62 MB 75% 13.68 MB 70% 12.81 MB 65% 11.87 MB 60% 10.93 MB 55% 10.06 MB 50% 9.12 MB 45% 8.18 MB 40% 7.31 MB 35% 6.37 MB 30% 5.43 MB 25% 4.56 MB 20% 3.62 MB 15% 2.68 MB 10% 1.81 MB 5% 896.00 KB * Current size of the Performance tier: 44.87 GB Percent of total I/Os serviced from the Performance tier: 89% Size of files pinned to the Performance tier: 0 bytes Percent of total I/Os: 0% Size of files pinned to the Capacity tier: 0 bytes Percent of total I/Os: 0% I think we can now declare victory Hopefully this is enough to help other people do similar stupid things, like use undocumented, unsupported, enterprise storage technologies on their home machines.
Right, little update here. This week I've started to get some weird hangs in Windows, which I tracked down to anything that attempted to access my tiered mirror drive. A quick check in the Storage Spaces GUI confirmed my fears, one of the SSDs I was using as a cache was showing a warning. Fortunately 60GB SSDs are cheap as chips these days, so I grabbed a new one (well, two, I'm expecting the other Kingston SSD to go bad one of these days), and went to plug it in. First problem, the bad SSD had got so bad that the system wouldn't boot with it plugged in. Fortunately I'd made a note of the serial number of the failed one where it was listed in the StorageSpaces GUI. So, here's my little howto on "oh **** one of my tiered SSDs has died how do I fix it?" First, go into the Storage Spaces GUI and work out which one it is. Make sure to write down the SN so you unplug the right one (important if you're using otherwise identical drives). Get hold of a new disk of at least the same size (and maybe think about grabbing a pre-emptive replacement for the other SSD) and plug it in. (I've temporarily unplugged my DVD drive to give me a spare SATA port). Once the new disk is connected, boot up and go check it's detected in Disk Management, or use Powershell: Code: Get-PhysicalDisk Number FriendlyName MediaType CanPool OperationalStatus HealthStatus Usage Size ------ ------------ --------- ------- ----------------- ------------ ----- ---- SSD1 SSD False Lost Communication Warning Retired 55.75 GB 2 TOSHIBA HDD False OK Healthy Auto-Select 3.64 TB 3 ST4000VN000-1H4168 HDD False OK Healthy Auto-Select 3.64 TB 1 SSD2 SSD False OK Healthy Auto-Select 55.75 GB 9 Corsair Force LS SSD SSD False OK Healthy Auto-Select 55.9 GB 4 WDC WD40EZRZ HDD False OK Healthy Auto-Select 3.64 TB The top line is my broken (and now disconnected) SSD, the new one is disk no. 9 (the Corsair drive) Now the new disk had some previous partitions on, so they need to be removed first. As there's only one Corsair drive this isn't too tricky: WARNING, this will wipe the disk, so be really bloody careful that it's the right one! Code: Reset-PhysicalDisk -FriendlyName "Corsair Force LS SSD" Now we just need to add it to the pool: First, create a variable who's contents is the new disk Code: $corse = Get-PhysicalDisk -FriendlyName "Corsair Force LS SSD" Now add that disk Code: Add-PhysicalDisk -PhysicalDisks $corse -StoragePoolFriendlyName "Storage Pool" (the name of your storage pool may vary, but it will probably be the one above). That's it for the Powershell this time, although I suppose there's no reason you couldn't run Optimize-StoragePool right now. Otherwise, let's head back to the GUI and make sure our new disk is showing up. (I forgot to get screenshots so you'll just have to imagine this bit). Hopefully it's showing up, so click the 'Change Settings' button, and then 'Optimise drive usage'. This will copy all the data onto the new disk. This might take a little while to complete, but when it has, you can go ahead and click the 'Remove' button next to your fialed drive, so it's compltely gone from the pool. That's it, disk crisis averted, and my tiered storage space is still ticking along (and the strange lags and hangs I was getting are gone now that the failing SSD is disconnected).
Nice Overview, i'm thankfully was using it and pushed it bit more in some unsupported direction.. Before i follow with replacing failed disks, i have some kind of "mixed tiers" running which i believe i could not get to run on the Server.. i believe.. definitely not with the GUI This can be achieved by setting the resiliencySetting-Stuff when creating the StorageTier(s). I'm running my Fast Tier on 2 120GB SSD as a Stripe Set with doubled performance. The Capacity Tier i have started with 3 250 GB HDDs Running as Parity array, and added a 4th 250 GB disk later as i found that it is really working great.. The continuously automatic running (every 4 hrs.) optimization is really great, i nearly never getting low hdd speed on day by day usage, drop your data on it and it manages, to deliver it back at always - at least felt - SSD speed.. I was not sure if "-ResiliencySettingName Simple" will force to a RAID-0 like Stripe-Set, so the "-NumberOfColumns 2" is the just to make that sure an set's the striping over 2 disks. HDD Tier is straight forward plain RAID-5 -Kind Parity, a to put some failure tolerance, always a nice idea - even in pretty young Harddisks like mine my disks are about 14 years old, ran, from the youngest one 29.000hrs, to the leader with 43.000hrs... but running fine, they are just Consumer Disks with a MTBF of 30.000 i believe.. Short: Performance Tier: Stripeset 2xSSD, Capacity Tier 3 (extended later to 4) disks running as Parity Array: Code: New-StorageTier -StoragePoolFriendlyName Pool -FriendlyName SSDTier -MediaType SSD -ResiliencySettingName Simple -NumberOfColumns 2 New-StorageTier -StoragePoolFriendlyName Pool -FriendlyName HDDTier -MediaType HDD -ResiliencySettingName Parity !!! NOTICE: !!! On the next command, the "New-VirtualDisk" You MUST NOT enter any ot the ResiliencySetting - Stuff. It will always lead into an error as you cannot match 1 possible resilliency setting of the VirtualDisk and store it on BOTH, already DIFFERENTLY configured tiers.. ALL the parameters, columns, copies, faultDisktolerance - all the stuff.. when mixing 2 different raid-types and use it Tiered together - all this has to be set on the tier... !!! And you will enjoy the fun getting your not-too-high StorageTierSize for the Parity Array.. some value below 66% of all your ohysical Disk Total Size in the Pool. For example For One 250 GB its something around 150GB Per Disk, maybe below.. Notice that "250GB"-Label just derived from originally 250.xxx.xxx.xxx Bytes, which turns out into something around in 232GB which (No need to tell: next command requires to fill the $xxx_tier variables like mentioned above. - no guarantee for typo's - created some time ago, i don't have a secont pool of 6 disks ) Code: New-VirtualDisk -StoragePoolFriendlyName "Storage Pool" -FriendlyName "TierDisk" -StorageTiers @($ssd_tier, $hdd_tier) -StorageTierSizes @(220GB, 600GB)
Now the Process how to properly Exchange a broken Disk, forcing to start a rebuild and finally removing the no longer existent reference to the disintegrated Disk. you will mention that 50% of my Pool running on VHDs... Thats just because i don't own more same sized disks. Each VHD also is on a competely seperated physical disk. The crazy thing is, there are 4 more left 10 Physical devices are connected 3NVMe / 2SSD / 5HDD... Im a Disk messy Situation like written before: A Tiered Storage of a Performance Tier: Stripeset 2xSSD (total 220GB), and a Capacity Tier 4 disks running as Parity Array (Total 600GB). One of the HDDs just died, it completely disintegrated from this world, we'll never get it back By the way, The VirtualDisk on this is running fine all the time, slower, but fine, with no loss or interruption as the HHD-Tier runnig a Parity array which tolerates 1 failed disk. The status looks like this: Code: FriendlyName ResiliencySettingName FaultDomainRedundancy OperationalStatus HealthStatus Size FootprintOnPool StorageE fficienc y ------------ --------------------- --------------------- ----------------- ------------ ---- --------------- -------- TierDisk {Degraded, Incomplete} Warning 820 GB 1.11 TB 72,45 % 1. I've added a brand new, same sized HDD like the broken one was. Just connected, not added to pool yet. 2. Some preparing config on the disk.. setting a name fo know where its stored.. at this point, you will also set the "-MediaType" if its not correct After that, the current pool whith the broken one - new disk is still not added. Code: PS C:\WINDOWS\system32> Get-PhysicalDisk -DeviceNumber 11 Number FriendlyName SerialNumber MediaType CanPool OperationalStatus HealthStatus Usage Size ------ ------------ ------------ --------- ------- ----------------- ------------ ----- ---- 11 Msft Virtual Disk HDD True OK Healthy Auto-Select 232.88 GB PS C:\> Get-PhysicalDisk -DeviceNumber 11 | Set-PhysicalDisk -NewFriendlyName ON_WD1TB_HDD.vhdx PS C:\> Get-StoragePool pool | Get-PhysicalDisk Number FriendlyName SerialNumber MediaType CanPool OperationalStatus HealthStatus Usage Size ------ ------------ ------------ --------- ------- ----------------- ------------ ----- ---- 0 ST9250315AS 5VCBFP3X HDD False OK Healthy Auto-Select 232.89 GB 4 Intenso SSD Sata III AA000000000000006710 SSD False OK Healthy Auto-Select 118 GB 10 ON_WDNVME2_SSD.vhdx SSD False OK Healthy Auto-Select 119 GB ON_WD1TB_HDD.vhdx HDD False Lost Communication Warning Auto-Select 250 GB 2 SAMSUNG HD250HJ S0URJ90Q217456 HDD False OK Healthy Auto-Select 232.88 GB 9 ON_500GB_HDD.vhdx HDD False OK Healthy Auto-Select 232.89 GB Then i've isolated or filtered the defect disk entry - and tested it - good idea to test the query before piping it into something that will SET or DO something on the result 3. IMPORTANT STEP.. the last line in this block "Set-PhysicalDisk -Usage Retired" Retires the failed disk. Tell the system, it will never come back, it should no longer wait for - (and - not tested but logical outcome - it might tell the system to use the next added disk as replacement - not as extension of the pool) Code: PS C:\> Get-StoragePool pool | Get-PhysicalDisk -HealthStatus Warning Number FriendlyName SerialNumber MediaType CanPool OperationalStatus HealthStatus Usage Size ------ ------------ ------------ --------- ------- ----------------- ------------ ----- ---- ON_WD1TB_HDD.vhdx HDD False Lost Communication Warning Auto-Select 250 GB PS C:\> Get-StoragePool pool | Get-PhysicalDisk -HealthStatus Warning | Set-PhysicalDisk -Usage Retired And just straight through 4. Add the spare disk into the Storage-Pool, the "-Usage AutoSelect" should trigger the System to start the rebuilt more or less immediately. 5. We can confirm this by the status change on the VirtualDisk, from "Missing" into "InService" Code: PS C:\> Add-PhysicalDisk -StoragePoolFriendlyName Pool -PhysicalDisks (Get-PhysicalDisk -DeviceNumber 11) -Usage AutoSelect PS C:\> Get-StoragePool pool | Get-PhysicalDisk Number FriendlyName SerialNumber MediaType CanPool OperationalStatus HealthStatus Usage Size ------ ------------ ------------ --------- ------- ----------------- ------------ ----- ---- 0 ST9250315AS 5VCBFP3X HDD False OK Healthy Auto-Select 232.89 GB 4 Intenso SSD Sata III AA000000000000006710 SSD False OK Healthy Auto-Select 118 GB 10 ON_WDNVME2_SSD.vhdx SSD False OK Healthy Auto-Select 119 GB ON_WD1TB_HDD.vhdx HDD False Lost Communication Warning Retired 250 GB 2 SAMSUNG HD250HJ S0URJ90Q217456 HDD False OK Healthy Auto-Select 232.88 GB 9 ON_500GB_HDD.vhdx HDD False OK Healthy Auto-Select 232.89 GB 11 ON_WD1TB_HDD.vhdx HDD False OK Healthy Auto-Select 232.88 GB PS C:\> Get-StoragePool pool | Get-VirtualDisk FriendlyName ResiliencySettingName FaultDomainRedundancy OperationalStatus HealthStatus Size FootprintOnPool StorageEfficiency ------------ --------------------- --------------------- ----------------- ------------ ---- --------------- ----------------- TierDisk InService Warning 820 GB 1.33 TB 60,33 % You could, if needed, or just to have a progress bar on the screen, manually invoke the rebuild by: Code: PS C:\> Get-StoragePool pool | Get-VirtualDisk | Repair-VirtualDisk From now, the Tiers will make it back into produktion just after finishing the rebuilt, we still have one thing left - the broken disk (basically the dead reference to it - as the pysical disk already disintegrated from this planet). You can invoke it now, while the rebuild is running but it will take - and block your 2nd Powershell-Window - as long as the rebuild takes... because it waits for it... 6. Pretty straigt forward, Remove-PhysicalDisk 7. Be happy to watch your system went back to healthy.. *but just maybe for PS-Rookies notice the "Remove-PhysicalDisk" command wants to have the "-PhysicalDisks" as system object, no name or sth, as well as you cannot pipe it into it.. You will need to either to query the disk before and set that into a $variable, or - the lazy way i did, put your disk-query into brackets for the value of the parameter "-PhysicalDisks" - that forces the command inside the brackets to be run before the command around it, so the parameter will be set with the output of the command inside brackets... Code: PS C:\> Remove-PhysicalDisk -StoragePoolFriendlyName Pool -PhysicalDisks (Get-StoragePool pool| Get-PhysicalDisk -Usage Retired -HealthStatus Warning) Bestätigung Möchten Sie diese Aktion wirklich ausführen? Removing a physical disk will cause problems with the fault tolerance capabilities of the following storage pool: "Pool". [J] Ja [A] Ja, alle [N] Nein [K] Nein, keine [H] Anhalten [?] Hilfe (Standard ist "J"): j PS C:\WINDOWS\system32> Get-Storagepool pool| Get-PhysicalDisk Number FriendlyName SerialNumber MediaType CanPool OperationalStatus HealthStatus Usage Size ------ ------------ ------------ --------- ------- ----------------- ------------ ----- ---- 0 ST9250315AS 5VCBFP3X HDD False OK Healthy Auto-Select 232.89 GB 4 Intenso SSD Sata III AA000000000000006710 SSD False OK Healthy Auto-Select 118 GB 10 ON_WDNVME2_SSD.vhdx SSD False OK Healthy Auto-Select 119 GB 2 SAMSUNG HD250HJ S0URJ90Q217456 HDD False OK Healthy Auto-Select 232.88 GB 9 ON_500GB_HDD.vhdx HDD False OK Healthy Auto-Select 232.89 GB 11 ON_WD1TB_HDD.vhdx HDD False OK Healthy Auto-Select 232.88 GB PS C:\> Get-StoragePool | Get-VirtualDisk FriendlyName ResiliencySettingName FaultDomainRedundancy OperationalStatus HealthStatus Size FootprintOnPool StorageEfficiency ------------ --------------------- --------------------- ----------------- ------------ ---- --------------- ----------------- TierDisk OK Healthy 820 GB 1.1 TB 72,99 % Short Story long.. peace