What is the best way to use DataStore for saving a lot of values and assets

I am creating an RPG style game and I want to find the best way to store cosmetics, upgrades, inventory, values, weapons, gear etc.

For what I did recently in a game I’m working on, I put the values inside of a PlayerData folder inside of ReplicatedStorage, Saved those values and loaded them back onto the folder whenever they would join.

Instead of using the leaderstats this is what I used so it wouldn’t show on the Player Leaderboard.

local function saveData(player)

	local success, err = pcall(function()
		local d = {player.leaderstats.Dogecoins.Value, player.leaderstats.Level.Value, game.ReplicatedStorage.PlayerData[player.UserId].CurrentXP.Value, game.ReplicatedStorage.PlayerData[player.UserId].FillXP.Value, game.ReplicatedStorage.PlayerData[player.UserId].OreData.InventoryWorth.Value}
		for _, ore in pairs(game.workspace.Ores:GetChildren()) do
			if ore[ore.Name]:FindFirstChild("Server") then
				table.insert(d, game.ReplicatedStorage.PlayerData[player.UserId].OreData[ore.Name].Value)
		dataStore:SetAsync("Dogecoins_" .. player.UserId, d[1])
		dataStore:SetAsync("Level_" .. player.UserId, d[2])
		dataStore:SetAsync("CurrentXp_" .. player.UserId, d[3])
		dataStore:SetAsync("FillXP_" .. player.UserId, d[4])
		dataStore:SetAsync("InventoryWorth_" .. player.UserId, d[5])
		for _, ore in pairs(game.workspace.Ores:GetChildren()) do
				dataStore:SetAsync(ore.Name .. "_" .. player.UserId, game.ReplicatedStorage.PlayerData[player.UserId].OreData[ore.Name].Value)

	if not success then

I had 2 loops, one to add all of the data to the data table, and then the other to save it when the function is called (I reccommend if you are using this method to use Player.UserId instead of Usernames, this can lead to players getting other users data’s). This is optional because im working on a game where I don’t want to nessicarilly have all of the values already exist

(Sorry for so many edits)