Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update service tuning docs #672

Merged
merged 1 commit into from
Sep 2, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 0 additions & 36 deletions docs-2.0/20.appendix/2.graph-modeling.md

This file was deleted.

73 changes: 73 additions & 0 deletions docs-2.0/8.service-tuning/2.graph-modeling.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
## Graph data modeling suggestions

This section provides general suggestions for modeling data in Nebula Graph.

!!! note

The following suggestions may not apply to some special scenarios. In these cases, find help in the [Nebula Graph community](https://discuss.nebula-graph.io/).

### Model for performance

There is no perfect method to model in Nebula Graph. Graph modeling depends on the questions that you want to know from the data. Your data drives your graph model. Graph data modeling is intuitive and convenient. Create your data model based on your business model. Test your model and gradually optimize it to fit your business. To get better performance, you can change or re-design your model multiple times.

### Design and evaluate the most important queries

Usually, various types of queries are validated in test scenarios to assess the overall capabilities of the system. However, in most production scenarios, there are not many types of frequently used queries. You can optimize the data model based on key queries selected according to the Pareto (80/20) principle.

### No predefined bonds between Tags and Edge types

Define the bonds between Tags and Edge types in the application, not Nebula Graph. There are no statements that could get the bonds between Tags and Edge types.

### Tags/Edge types predefine a set of properties

While creating Tags or Edge types, you need to define a set of properties. Properties are part of the Nebula Graph Schema.

### Control changes in the business model and the data model

Some graph databases are designed to be Schema-free, so their data modeling, including the modeling of the graph topology and properties, can be very flexible. Properties can be re-modeled to graph topology, and vice versa. Such systems are often specifically optimized for graph topology access.

Nebula Graph {{ nebula.release }} is a strong-Schema (row storage) system, which means that the business model should not change frequently. For example, the property Schema should not change. It is similar to avoiding `ALTER TABLE` in MySQL.

On the contrary, vertices and their edges can be added or deleted at low costs. Thus, the easy-to-change part of the business model should be transformed to vertices or edges, rather than properties.

For example, in a business model, people have relatively fixed properties such as age, gender, and name. But their contact, place of visit, trade account, and login device are often changing. The former is suitable for modeling as properties and the latter as vertices or edges.

### Breadth-first traversal over depth-first traversal

Nebula Graph has lower performance for depth-first traversal based on the Graph topology, and better performance for breadth-first traversal and obtaining properties. For example, if model A contains properties "name", "age", and "eye color", it is recommended to create a Tag `person` and add properties `name`, `age`, and `eye_color` to it. If you create a Tag `eye_color` and an Edge type `has`, and then create an edge to represent the eye color owned by the person, the traversal performance will not be high.

The performance of finding an edge by an edge property is close to that of finding a vertex by a vertex property. For some databases, it is recommended to re-model edge properties as those of the intermediate vertices. For example, model the pattern `(src)-[edge {P1, P2}]->(dst)` as `(src)-[edge1]->(i_node {P1, P2})-[edge2]->(dst)`. With Nebula Graph {{ nebula.release }}, you can use `(src)-[edge {P1, P2}]->(dst)` directly to decrease the depth of the traversal and increase the performance.

### Edge directions

To query in the opposite direction of an edge, use the syntax `(dst)<-[edge]-(src)` or `GO FROM dst REVERSELY`.

If you don't care about the directions or want to query against both directions, use the syntax `(src)-[edge]-(dst)` or `GO FROM src BIDIRECT`.

Therefore, there is no need to insert the same edge redundantly in the reversed direction.

### Set Tag properties appropriately

Put a group of properties that are on the same level into the same Tag. Different groups represent different concepts.

### Use indexes correctly

Using property indexes helps find VIDs through properties, but can lead to performance decrease by 90% or even more. Only use an index when you need to find vertices or edges through their properties.

### Design VIDs appropriately

See [VID](../1.introduction/3.vid.md).

### Long texts

Do not use long texts to create edge properties. Edge properties are stored twice and long texts lead to greater write amplification. For how edges properties are stored, see [Storage architecture](../1.introduction/3.nebula-graph-architecture/4.storage-service.md). It is recommended to store long texts in HBase or Elasticsearch and store its address in Nehula Graph.

## Dynamic graphs (sequence graphs) are not supported

In some scenarios, graphs need to have time information to describe how the structure of the entire graph changes over time.[^twitter]

The Rank field on Edges in Nebula Graph {{ nebula.release }} can be used to store time in int64, but no field on vertices can do this because if you store the time information as property values, it will be covered by new insertion. Thus Nebula Graph does not support sequence graphs.

![image](sequence.png)

[^twitter]: https://blog.twitter.com/engineering/en_us/topics/insights/2021/temporal-graph-networks
40 changes: 40 additions & 0 deletions docs-2.0/8.service-tuning/3.system-design.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# System design suggestions

## QPS or low-latency first

Nebula Graph is good at handling small requests with high concurrency. In such scenarios, the whole graph is huge, containing maybe trillions of vertices, but the subgraphs accessed by each request are not large (containing millions of vertices or edges), and the latency of a single request is low. The concurrent number of such requests, i.e., the QPS, can be huge.

On the other hand, in interactive analysis scenarios, the request concurrency is usually not high, but the subgraphs accessed by each request are large, with thousands of millions of vertices or edges. To lower the latency of big requests in such scenarios, you can split big requests into multiple small requests in the application, and send them to multiple Graph servers. This can decrease the memory used by each Graph server as well. Besides, you can use [Nebula Algorithm](../nebula-algorithm.md) for such scenarios.

## Horizontal or vertical scaling

Nebula Graph {{ nebula.release }} supports horizontal scaling.

+ The horizontal scaling of the Storage Service:

Increasing the number of Storage machines increases the overall capability of the cluster linearly, including increasing overall QPS and reducing latency.

However, the number of partitions is fixed when creating a graph space. The service capability of a single partition is determined by a single server. The operations depending on a single partition include fetching properties of a single vertex (`FETCH`), a breadth-first traversal from a single vertex (`GO`), etc.

+ The horizontal scaling of the Graph Service:

Each request from the client is handled by one and only one Graph server, with no other Graph servers participating in the processing of the request. Therefore, increasing the number of Graph machines can increase the overall QPS of the cluster, but cannot lower the latency of a single request.

+ Metad does not support horizontal scaling.

Vertical scaling usually has higher hardware costs, but relatively simple operations. Nebula Graph {{Nebula. Release}} can also be scaled vertically.

## Data transmission and optimization

- Read/write balance. Nebula Graph fits into OLTP scenarios with balanced read/write, i.e., concurrent write and read. It is not suitable for OLAP scenarios that usually need to write once and read many times.
- Select different write methods. Write large batches of data with SST files, and small batches of data with `INSERT` statements.
- Run `COMPACTION` and `BALANCE` jobs to optimize data format and storage distribution at the right time.
- Nebula Graph {{ nebula.release }} N Does not support transactions and isolation in the relational database sense and is closer to NoSQL.

## Query preheating and data preheating

Preheat on the application side:

- The Graph Service does not support pre-compiling queries and generating corresponding query plans, nor can it cache previous query results.
- The Storage Service does not support preheating data, and only the LSM-Tree and BloomFilter of RocksDB are loaded into memory at startup.
- Once accessed, vertices and edges are cached respectively in two types of LRU cache of the Storage Service.
5 changes: 5 additions & 0 deletions docs-2.0/8.service-tuning/4.plan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Execution plan

Nebula Graph {{ nebula.release }} applies rule-based execution plans. Users cannot change execution plans, precompile queries and corresponding plan cache, or accelerate queries by specifying indexes.

To view the execution plan and executive summary, see [EXPLAIN and PROFILE](../3.ngql-guide/17.query-tuning-statements/1.explain-and-profile.md).
20 changes: 16 additions & 4 deletions docs-2.0/8.service-tuning/compaction.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ Nebula Graph has two types of compaction: automatic compaction and full compacti

## Automatic compaction

Automatic compaction is done when the system reads data, writes data, or the system restarts. The automatic compaction is enabled by default. But once triggered during peak hours, it can cause unexpected IO occupancy that has an unwanted effect on the performance. To disable automatic compaction, use this statement:
Automatic compaction is done when the system reads data, writes data, or the system restarts. Automatic compaction is enabled by default.

<!--
But once triggered during peak hours, it can cause unexpected IO occupancy that has an unwanted effect on the performance. To disable automatic compaction, use this statement:

```ngql
nebula> UPDATE CONFIGS storage:rocksdb_column_family_options = {disable_auto_compactions = true};
Expand All @@ -22,6 +25,8 @@ nebula> UPDATE CONFIGS storage:rocksdb_column_family_options = {disable_auto_com

The command overwrites all `rocksdb_column_family_options` items. Other items besides `disable_auto_compactions` is overwritten to the default value. You may have to read all the items before the updates.

-->

## Full compaction

Full compaction enables large scale background operations for a graph space such as merging files, deleting the data expired by TTL. Use these statements to enable full compaction:
Expand All @@ -45,15 +50,22 @@ nebula> SHOW JOB <job_id>;

These are some operation suggestions to keep Nebula Graph performing well.

<!--
- To avoid unwanted IO waste during data writing, set `disable_auto_compactions` to `true` before large amounts of data writing.
-->

- After data import is done, run `SUBMIT JOB COMPACT`.

- Run `SUBMIT JOB COMPACT` periodically during off-peak hours, for example, early morning.

<!--
- Set `disable_auto_compactions` to `false` during day time.
- To control the read and write traffic limitation for compactions, set these two parameters in the `nebula-storaged.conf` configuration file.
-->

- To control the read and write traffic limitation for compactions, set the following parameter in the `nebula-storaged.conf` configuration file.

```bash
# read from the local configuration file and start
--local-config=true
# Limit the read/write rate to 20MB/s.
--rate_limit=20 (in MB/s)
```

Expand Down
9 changes: 4 additions & 5 deletions docs-2.0/8.service-tuning/load-balance.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ nebual> SHOW HOSTS;
+-------------+------+----------+--------------+-----------------------------------+------------------------+
| "Total" | | | 15 | "basketballplayer:15" | "basketballplayer:45" |
+-------------+------+----------+--------------+-----------------------------------+------------------------+
Got 6 rows (time spent 1002/1780 us)
```

Run `BALANCE DATA` to start balancing the storage partitions. If the partitions are already balanced, `BALANCE DATA` fails.
Expand All @@ -47,7 +46,6 @@ nebula> BALANCE DATA;
+------------+
| 1614237867 |
+------------+
Got 1 rows (time spent 3783/4533 us)
```

A BALANCE task ID is returned after running `BALANCE DATA`. Run `BALANCE DATA <balance_id>` to check the status of the `BALANCE` task.
Expand All @@ -67,7 +65,6 @@ nebula> BALANCE DATA 1614237867;
+--------------------------------------------------------------+-------------------+
| "Total:22, Succeeded:22, Failed:0, In Progress:0, Invalid:0" | 100 |
+--------------------------------------------------------------+-------------------+
Got 23 rows (time spent 916/1528 us)
```

When all the subtasks succeed, the load balancing process finishes. Run `SHOW HOSTS` again to make sure the partition distribution is balanced.
Expand All @@ -93,7 +90,6 @@ nebula> SHOW HOSTS;
+-------------+------+----------+--------------+-----------------------------------+------------------------+
| "Total" | | | 15 | "basketballplayer:15" | "basketballplayer:45" |
+-------------+------+----------+--------------+-----------------------------------+------------------------+
Got 6 rows (time spent 849/1420 us)
```

If any subtask fails, run `BALANCE DATA` again to restart the balancing. If redoing load balancing does not solve the problem, ask for help in the [Nebula Graph community](https://discuss.nebula-graph.io/).
Expand All @@ -116,6 +112,10 @@ Once all the subtasks are finished or stopped, you can run `BALANCE DATA` again

* If no subtask of the preceding balance task failed, Nebula Graph starts a new balance task.

## RESET a balance task

If a balance task fails to be restarted after being stopped, run `BALANCE DATA RESET PLAN` to reset the task. After that, run `BALANCE DATA` again to start a new balance task.

## Remove storage servers

To remove specific storage servers and scale in the Storage Service, use the `BALANCE DATA REMOVE <host_list>` syntax.
Expand Down Expand Up @@ -145,7 +145,6 @@ Nebula Graph will start a balance task, migrate the storage partitions in storag

```ngql
nebula> BALANCE LEADER;
Execution succeeded (time spent 7576/8657 us)
```

Run `SHOW HOSTS` to check the balance result.
Expand Down
Binary file added docs-2.0/8.service-tuning/sequence.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading