Data Storage / Các collection
Tất cả data lưu trữ trên NEAR blockchain được thực hiện theo cặp key / value. Có một số collection method trong SDK mà chúng tôi đã tạo sẽ giúp bạn lưu trữ data on chain.
near-sdk-rs
for Rust smart contractsnear-sdk-js
for JavaScript smart contracts
For information on storage costs, please see [ storage staking ].
Rust Collection Types
near-sdk-rs
module documentation
Type | Iterable | Clear All Values | Preserves Insertion Order | Range Selection |
---|---|---|---|---|
Vector | ✅ | ✅ | ✅ | ✅ |
LookupSet | ||||
UnorderedSet | ✅ | ✅ | ✅ | |
LookupMap | ||||
UnorderedMap | ✅ | ✅ | ✅ | |
TreeMap | ✅ | ✅ |
Chú thích Big-O
Các value Big-O notation trong biểu đồ bên dưới mô tả time complexity của nhiều collection method trong
near-sdk-rs
. Sự phức tạp của các method này liên quan tới sự tiêu thụ gas trên NEAR, từ đó giúp bạn quyết định collection nào sẽ được dùng trong dự án của bạn. Có 3 loại trong các collection method của chúng tôi:
- O(1) - constant
- O(n) - linear
- O(log n) - logarithmic
Type | Access | Insert | Delete | Search | Traverse | Clear |
---|---|---|---|---|---|---|
Vector | O(1) | O(1)* | O(1)** | O(n) | O(n) | O(n) |
LookupSet | O(1) | O(1) | O(1) | O(1) | N/A | N/A |
UnorderedSet | O(1) | O(1) | O(1) | O(1) | O(n) | O(n) |
LookupMap | O(1) | O(1) | O(1) | O(1) | N/A | N/A |
UnorderedMap | O(1) | O(1) | O(1) | O(1) | O(n) | O(n) |
TreeMap | O(1) | O(log n) | O(log n) | O(log n) | O(n) | O(n) |
** - để xóa từ cuối vector thì dùng pop
(hoặc pop_front
để deque), hoặc khi xóa bằng swap_remove
sẽ swap element với element cuối cùng của vector và sau đó remove nó.
** - to delete from the end of the vector using pop
(or pop_front
for deque), or delete using swap_remove
which swaps the element with the last element of the vector and then removes it.
Gas Consumption Examples
Các ví dụ dưới đây cho thấy sự khác biệt trong việc việc đốt gas để lưu trữ và truy xuất các cặp key/value bằng cách sử dụng các method trên. Xin lưu ý rằng chi phí gas để khởi động runtime environment trên chain đã được lược bỏ, nhằm mục đích chỉ hiển thị dữ liệu đọc/ghi.
You can reproduce this and test out your own data set by visiting collection-examples-rs.
Vector
Implements a vector / persistent array.
- can iterate using index
- Uses the following map: index -> element.
[ SDK source ]
[ Implementation ]
LookupSet
Implements a persistent set without iterators.
- can not iterate over keys
- more efficient in reads / writes
[ SDK source ]
[ Implementation ]
UnorderedSet
Được build trên class
Storage
, điều này implement một persistent set mà không có các iterator.
[ SDK source ]
LookupMap
Implement một map được build trên
Storage
.
- can not iterate over keys
- does not preserve order when removing and adding values
- efficient in number of reads and writes
- Để sử dụng:
pub fn add_lookup_map(&mut self, key: String, value: String) {
self.lookup_map.insert(&key, &value);
}
- Để tạo:
pub fn get_lookup_map(&self, key: String) -> String {
match self.lookup_map.get(&key) {
Some(value) => {
let log_message = format!("Value from LookupMap is {:?}", value.clone());
env::log(log_message.as_bytes());
value
},
None => "not found".to_string()
}
}
[ SDK source ]
[ Implementation ]
UnorderedMap
Implements an unordered map.
- iterable
- does not preserve order when removing and adding values
- is able to clear all values
- Để sử dụng:
pub fn add_unordered_map(&mut self, key: String, value: String) {
self.unordered_map.insert(&key, &value);
}
- Để tạo:
pub fn get_unordered_map(&self, key: String) -> String {
match self.unordered_map.get(&key) {
Some(value) => {
let log_message = format!("Value from UnorderedMap is {:?}", value.clone());
env::log(log_message.as_bytes());
value
},
// None => "Didn't find that key.".to_string()
None => "not found".to_string()
}
}
[ SDK source ]
[ Implementation ]
TreeMap
Được build trên class
Storage
, nó implement một a persistent bidirectional queue / double-ended queue / deque.
- iterable
- preserves order
- able to clear all values
- self balancing
- Để sử dụng:
pub fn add_tree_map(&mut self, key: String, value: String) {
self.tree_map.insert(&key, &value);
}
- Để tạo:
map.set(key, value);
map.getSome(key);
[ SDK source ]
[ Implementation ]
Storage Constraints on NEAR
For storing data on-chain it’s important to keep in mind the following:
- Can add up in storage staking costs
- There is a 4mb limit on how much you can upload at once
Let’s say for example, someone wants to put an NFT purely on-chain (rather than IPFS or some other decentralized storage solution) you’ll have almost an unlimited amount of storage but will have to pay 1 $NEAR per 100kb of storage used (see Storage Staking).
Users will be limited to 4MB per contract call upload due to MAX_GAS constraints. The maximum amount of gas one can attach to a given functionCall is 300TGas.