If you could go with tables, then do it. From my own experience, i'd say that tables are way more efficient rather than element data. However you should remember about few things, when it comes to passing data (doesn't matter if it's element data or tables).
1) How often data is passed - the less - the better (use timers for reduction, aka buffers; collect pack of data, and then send it after 100-200 ms).
2) How much data do you pass - if you do not need to pass whole data, then don't do it (unless on init). Send certain values.
3) How you pass data - it should be well maintained to avoid issues. With tables it's easier to do. Haven't using using element data for a long time, but i'm pretty sure that:
setElementData(client, "data", true) -- equals to 1 triggerClientEvent
So every call of element data is one trigger, which is pretty bad. Imagine that you need to set 30 data at once (feels bad). You can see that tables won here
local dataTable = {}
local playerElement = getPlayerFromName("SERIOUSLY?")
dataTable[playerElement] = {}
dataTable[playerElement][1] = "First index."
dataTable[playerElement][2] = "Second index."
triggerClientEvent(root, "onClientDataSync", resourceRoot, dataTable) -- 1 call
setElementData(playerElement, "First index", true) -- 1 call
setElementData(playerElement, "Second index", true) -- 2 call
-- Element data will trigger separately for each call.
4) Don't do those:
local players = getElementsByType("player")
local playerElement = false
for i = 1, #players do
playerElement = players[i]
triggerClientEvent(playerElement, "onClientEvent", playerElement)
end
This will cause that triggerClientEvent will be called * count of players.
Instead do:
local players = getElementsByType("player")
triggerClientEvent(players, "onClientEvent", resourceRoot)
Since triggerClientEvent accepts table of players. And it would be just one call.
Extra code to test by @IIYAMA.
local sendingDelay = 100 -- ms
local fps = 60
local timeSlice = 1000/fps
local dataReduction = sendingDelay/timeSlice
print("~"..(dataReduction - 1 ).." x times LESS per "..sendingDelay.."ms")
You can see how certain delays affect server when passing data.
If you have any other questions, feel free to ask.
PS: Recently element data got some update with subscription mode, but i still advice to go for tables if you can