- Published on
SurrealDB first look
- Authors
- Name
- Omer ATAGUN
Some developments ( inventions ) gets me excited. Yes, i am not talking about new javascript framework forget those.
SurrealDB ?
What isWell by the promises they have made, it is indeed SurrealDB and its up to us to test it out if those promises are actually true. We will be quick looking the features it promises, then do a basic for loop and force both surrealdb
and mariadb
to find out differences.
Installation
From their documentation in github repository. I came up with this docker command to fast skip all the setups that we need for testing the environment. So run
docker run --rm --name surrealdb -p 127.0.0.1:8002:8000 surrealdb/surrealdb:latest start --log trace --user root --pass root memory
We will be firing up a surrealdb on port 8002. Instance with memory option rather file this time. We will also test the file, no worries.
Lets get ourselves SDK/driver of surrealdb ( currently on node, deno, rust and golang ) for node.
Install driver via npm
Create a folder and run
npm install --save surrealdb.js
touch app.js
Now open your app.js
const Surreal = require('surrealdb.js');
const db = new Surreal('http://127.0.0.1:8002/rpc');
async function main() {
try {
// Signin as a namespace, database, or root user
await db.signin({
user: 'root',
pass: 'root',
});
// Select a specific namespace / database
await db.use('test', 'test');
const insertRandomPersonGreedy = async () => {
console.time("dbsave")
for (let i = 0; i < 10000; i++) {
await db.create("person", {
title: 'Founder & CEO',
name: {
first: 'Tobie',
last: 'Morgan Hitchcock',
},
marketing: true,
identifier: Math.random().toString(36).substr(2, 10),
});
}
}
await insertRandomPersonGreedy().then(r=>{
console.timeEnd("dbsave")
})
let peeps = await db.select("person");
console.log(peeps.length)
} catch (e) {
console.error('ERROR', e);
}
}
main();
For the sake of the test, we set our loop to 10.000 records. So in one breath, we do be inserting 10.000 records. Greedy enough.
Run;
node app.js
Outcome
- My environment at this very moment is
Chip: Apple M1 Pro
Total Number of Cores: 10 (8 performance and 2 efficiency)
Memory: 16 GB
Result for this instance following
Time elapsed: 7.413s
Record in DB: 10000
Its time to kill our instance, recreate as file driver.
Run;
docker run --rm --name surrealdb -p 127.0.0.1:8002:8000 surrealdb/surrealdb:latest start --log trace --user root --pass root file://.
## output
[2022-09-17 06:43:19] INFO surrealdb::iam Root authentication is enabled
[2022-09-17 06:43:19] INFO surrealdb::iam Root username is 'root'
[2022-09-17 06:43:19] INFO surrealdb::dbs Database strict mode is disabled
[2022-09-17 06:43:19] INFO surrealdb::kvs Starting kvs store at file://.
[2022-09-17 06:43:19] INFO surrealdb::kvs Started kvs store at file://.
[2022-09-17 06:43:19] INFO surrealdb::net Starting web server on 0.0.0.0:8000
[2022-09-17 06:43:19] INFO surrealdb::net Started web server on 0.0.0.0:8000
[2022-09-17 06:43:20] INFO surreal::web 172.17.0.1:64468 GET /rpc HTTP/1.1 101 "-" 66.875µs
Run again our app.js so we measure whats the time elapsed;
node app.js
Time elapsed: 7.919s
Record in DB: 10000
Almost no difference at this very moment.
Lets go with node and mariadb
For this test, we use mariadb 10.7 as docker container. To make our life easier, i am giving you compose file so we can quickly set our table and all that stuff which we did not need while using surrealdb :)
create a file in same folder `docker-compose.yaml
version: '2.3'
services:
mysql:
restart: always
image: mariadb:10.7
container_name: mariadb
ports:
- "3307:3306"
volumes:
- ./store/:/var/lib/mysql
mem_limit: 5012m
networks:
- mysqlnetwork
environment:
- MYSQL_ROOT_PASSWORD=root
- MYSQL_DATABASE=local
- MYSQL_USER=root
- MYSQL_PASSWORD=root
- PMA_ARBITRARY=1
- PMA_HOST=mysql
- PMA_PORT=3306
- PMA_USER=root
- PMA_PASSWORD=root
mysql-admin:
restart: always
image: phpmyadmin/phpmyadmin
container_name: mariadb-phpmyadmin
ports:
- "8001:80"
mem_limit: 5012m
networks:
- mysqlnetwork
depends_on:
- mysql
environment:
PMA_HOST: mysql
PMA_PORT: 3306
PMA_USER: root
PMA_PASSWORD: root
UPLOAD_LIMIT: 30000M
networks:
mysqlnetwork:
driver: bridge
Run;
docker compose up
Wait a while till images are pulled. Then visit http://localhost:8001
Create a database named with
surreal
Create a table named with
person
PhpMysql by default will ask 4 columns, lets fill them up
id - int - 11 auto_increment (AI)
name- varchar 255
surname - varchar 255
title - varchar 255
click save
Now we can get our node app
Go to the folder where we have app.js
and create new file yapp.js
npm install mariadb --save
In our yapp.js
Note: by using same math random, we tried to keep the cost same.
const mariadb = require('mariadb');
const pool = mariadb.createPool({
host: '127.0.0.1',
database: 'surreal',
port: 3307,
user:'root',
password: 'root',
});
async function main(){
const conn = await pool.getConnection()
try{
const runGreedyQuery = async () => {
console.time("dbsave")
for(let i = 0; i<10000; i++){
const randomMath = Math.random().toString(36).substr(2, 10)
await conn.query(`INSERT INTO person (name,surname,title) values ('myname', 'mysurname', '${randomMath}')`);
}
}
await runGreedyQuery().then(r=>{
console.timeEnd("dbsave")
})
}catch(err){
console.log(err)
}
}
main()
Run;
node yapp.js
Output;
Time elapsed: 11.012s
Record in DB: 10000
Second run;
Time elapsed: 9.474s
Record in DB: 20000
Conclusion
There are observable differences in between two insert operations on different databases. Today, under these circumstances SurrealDB won. But that's not just enough to decide whether to go with one.
As we have said, we used same environment yet official images of both might be different. May affect the result. Let's set ourselves a mood of healthy skeptical to figure why we could put ourselves into an adventure by migrating to a new technology.
- Scaling Mysql or related forks of it as relational databases is hard to scale. We all know that already. To get yourself a single new column, You have to do your updates on database. Hell of a work and potential human errors. On this aspect, key-value storing like SurrealDB is great but not just it like other non-relation databases. SurrealDB provides a lot of features from relation-databases on its way. Some of those are;
Indexing
CREATE company:surrealdb SET name = 'SurrealDB', cofounders = [person:tobie, person:jaime];
This allows for records to be retrieved without any table scans or index scans, solely by the id. Beautiful.
NO JOINS but SurrealJoins :)
SELECT ->purchased->product<-purchased<-person->(purchased WHERE created_at > time::now() - 3w)->product FROM person:tobie;
- Transactions.
- Functions
- Statements
- Operators
And many more...
Honestly, i am excited to use it and see all the problems alongside benefits. There are a lot of built-in helpers SurrealDB provides. I belive its worth to take a look at all those promises.
Give your 10 minutes into documentation
Untill the next post, stay hydrated!