Collections
When deciding on data structures it is important to understand their tradeoffs. Choosing the wrong structure can create a bottleneck as the application scales, and migrating the state to the new data structures will come at a cost.
You can choose between two types of collections:
- Native collections (e.g.
Array
,Map
,Set
), provided by the the language - SDK collections (e.g.
IterableMap
,Vector
), provided by the NEAR SDK
Understanding how the contract stores and loads both types of collections is crucial to decide which one to use.
Use native collections for small amounts of data that need to be accessed all together, and SDK collections for large amounts of data that do not need to be accessed all together
Each time the contract is executed, the first thing it will do is to read the values and deserialize them into memory, and after the function finishes, it will serialize and write the values back to the database.
Native Collectionsโ
Native collections are those provided by the language:
- JS:
Array
,Set
,Map
,Object
... - Rust:
Vector
,HashMap
,Set
...
All entries in a native collection are serialized into a single value and stored together into the state. This means that every time a function execute, the SDK will read and deserialize all entries in the native collection.
Serialization & Storage Example
The array [1,2,3,4]
will be serialized into the JSON string "[1,2,3,4]"
in Javascript, and the Borsh byte-stream [0,0,0,4,1,2,3,4]
in Rust before being stored
Native collections are useful if you are planning to store smalls amounts of data that need to be accessed all together
As the native collection grows, deserializing it from memory will cost more and more gas. If the collections grows too large, your contract might expend all the gas trying to read its state, making it fail on each function call
SDK Collectionsโ
The NEAR SDKs expose collections that are optimized for random access of large amounts of data. SDK collections are instantiated using a "prefix", which is used as an index to split the data into chunks. This way, SDK collections can defer reading and writing to the store until needed.
These collections are built to have an interface similar to native collections.
Serialization & Storage Example
The sdk array [1,2,3,4]
with prefix "p"
will be stored as the string "p"
in the contract's attribute, and create four entries in the contract's storage: p-0:1
, p-1:2
...
SDK collections are useful when you are planning to store large amounts of data that do not need to be accessed all together
Exposed Collectionsโ
- ๐ JavaScript