<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Rafsun Masud</title>
    <description>The latest articles on DEV Community by Rafsun Masud (@rafsun42).</description>
    <link>https://dev.to/rafsun42</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1019659%2F8c4dc9fd-269d-4a66-bbbe-28473b71a553.jpg</url>
      <title>DEV Community: Rafsun Masud</title>
      <link>https://dev.to/rafsun42</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rafsun42"/>
    <language>en</language>
    <item>
      <title>How to amend changes to your pull request?</title>
      <dc:creator>Rafsun Masud</dc:creator>
      <pubDate>Thu, 23 Mar 2023 21:52:53 +0000</pubDate>
      <link>https://dev.to/rafsun42/how-to-amend-changes-to-your-pull-request-54fi</link>
      <guid>https://dev.to/rafsun42/how-to-amend-changes-to-your-pull-request-54fi</guid>
      <description>&lt;p&gt;So you have just received feedback on your PR. You forgot a semi-colon at the end of a line. After you fixed it, your commit history looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;5 (HEAD -&amp;gt; feature-branch) fix: add semi-colon (my bad)
4 add docs
3 write tests
2 implement feature
1 (master) base commit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;I know commit IDs are not integers. For the purpose of this article, you can assume they are. The base commit of your branch starts from 1, and continues to increase sequentially.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Also, notice that commit history always starts from the most recent commit down to the oldest commit.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It is a best practice to maintain a neat commit history. But yours is cluttered by a small fix commit now.&lt;/p&gt;

&lt;p&gt;To remove this clutter, you should amend the 4th commit into the 3rd. There are multiple ways of doing it. Rebasing the branch is one of them.&lt;/p&gt;

&lt;h2&gt;
  
  
  WARNING: The dark side of rebasing
&lt;/h2&gt;

&lt;p&gt;Before you go to rebasing a branch without reading the whole article, I must stop you. Rebasing modifies the commit history. When you push the rebased branch, your modified history (i.e. local copy) will replace the branch's current history residing in the upstream repository (i.e. GitHub). This is something you ABSOLUTELY don't want to do. Because next time anyone else pushes or pulls from the upstream repository, git will find mismatch in history and cause unexpected issues.&lt;/p&gt;

&lt;p&gt;A general rule of thumb is that do not modify a branch if more than one person is working on it. Ideally, your pull request is coming from a branch from a forked repo owned by you. And, you are the only person working on that branch most of the cases. In this situation, rebasing that branch is not a problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  What rebasing does under the hood
&lt;/h2&gt;

&lt;p&gt;When you rebase a branch, git will repeat the branch's history from the beginning (right after the base commit). It will remove all commits after 1, which are 2 to 5, from the commit history (not from the memory). Then, it will re-apply the commits from 2 to 5 sequentially. Before it starts re-applying, it will give you an opportunity to specify any modification you would like to make in the history. In your case, you want to specify that you want to squash the 5th commit into the 4th commit.&lt;/p&gt;

&lt;p&gt;Let's start the rebasing process. If you are afraid of playing with rebasing in your work repository, you may init a sample test repository and recreate the commit history we are dealing with now.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to perform rebasing
&lt;/h2&gt;

&lt;p&gt;Run the following command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git rebase -i HEAD~2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why &lt;code&gt;HEAD~2&lt;/code&gt;? Simply put, the command will repeat the last two commits, instead of the entire branch. Because you know you are modifying the last two commits in this case. If you really want to know what &lt;code&gt;HEAD~2&lt;/code&gt; means, it is a reference to the 3rd last commit (which is 3). The command is saying 'rebase all commits after the 3rd one into the 3rd one'. &lt;/p&gt;

&lt;p&gt;After you hit the command, git will open a text editor with the following content to give you a chance to specify the changes you want to make to the history of the last two commits.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pick 4 add docs
pick 5 fix: add semi-color (my bad)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Notice, this time git is showing the history from oldest to recent&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Modify the content by replacing &lt;code&gt;pick&lt;/code&gt; by &lt;code&gt;squash&lt;/code&gt; for the 5th commit. Save and close the text editor.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pick 4 add docs
squash 5 fix: add semi-color (my bad)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will be given another prompt to specify new commit message for the 4th commit. It will show you both commit messages from 4th and 5th. Simply comment out the commit message of the 5th commit. Save and close the editor.&lt;/p&gt;

&lt;p&gt;Git starts processing this commands from line 1. It re-applies the 4th commit. When it is time to re-apply the 5th commit, git sees the &lt;code&gt;squash&lt;/code&gt; command. So, it skips creating the 5th commit. Instead it ammends to contents of the 5th commit into the 4th. Basically, the 5th commit is squashed but its contents are retained by amending to the previous commit.&lt;/p&gt;

&lt;p&gt;Your job here is done!&lt;/p&gt;

&lt;h2&gt;
  
  
  Effects of rebasing
&lt;/h2&gt;

&lt;p&gt;If you now see the commit history, you will see that all rebased commits received a new commit ID.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;4' (HEAD -&amp;gt; feature-branch) add docs
3  write tests
2  implement feature
1  (master) base commit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This change in commit ID is what causes mismatch with upstream commit history.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pushing the updated history
&lt;/h2&gt;

&lt;p&gt;Now in your local commit history, the 'fix' commit is gone. And, it is time to update the upstream branch. &lt;/p&gt;

&lt;p&gt;Because your history is modified, you need to push with the &lt;code&gt;--force-with-lease&lt;/code&gt; option.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git push --force-with-lease
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As we have already discussed, don't force push if your branch has multiple people working on it.&lt;/p&gt;

&lt;p&gt;If you know go to the pull request page, you will see that updated history is reflected there. Also, you will see the any reference to the rebased commits made in the comments became invalid. But, they are not very important.&lt;/p&gt;

&lt;p&gt;I intentionally left out some details in this article. If you want me to expand, let me know in the comments.&lt;/p&gt;

</description>
      <category>git</category>
    </item>
    <item>
      <title>How Apache AGE turns a Relational DBMS into a Graph DBMS</title>
      <dc:creator>Rafsun Masud</dc:creator>
      <pubDate>Fri, 24 Feb 2023 23:44:10 +0000</pubDate>
      <link>https://dev.to/rafsun42/how-apache-age-turns-a-relational-dbms-into-a-graph-dbms-1i48</link>
      <guid>https://dev.to/rafsun42/how-apache-age-turns-a-relational-dbms-into-a-graph-dbms-1i48</guid>
      <description>&lt;p&gt;You may be wondering how it is possible to use tables to store and query a graph efficiently. Well, AGE has found its way of doing it.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;In case you have not heard of AGE yet, it is an open source graph database system built as an extension of Postgres. Checkout their &lt;a href="https://github.com/apache/age" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; page and official &lt;a href="https://age.apache.org" rel="noopener noreferrer"&gt;website&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;As someone who contributed to this project, I will explain how AGE does it and share some key insights on performance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Little background on Graph DBMS
&lt;/h2&gt;

&lt;p&gt;You will see two most common object in a AGE graph: vertex and edge. Generally, they are called entities or nodes.&lt;/p&gt;

&lt;p&gt;Each entity is made of a label and some properties. Properties are simply a collection of key-value pairs (similar to a JSON object). But, what is a label? Why is label a separate thing? Why can't it be part of the properties?&lt;/p&gt;

&lt;p&gt;Label is meant to provide categories (like students, professors), while properties are for details (like id, name, role etc.) Although you could still put category information inside properties, but using labels to categorise gives you performance advantage. In fact, labels do influence AGE's internal data structure, and you will see how.&lt;/p&gt;

&lt;h2&gt;
  
  
  Graphs are schemas
&lt;/h2&gt;

&lt;p&gt;AGE creates and uses a separate schema (a schema is basically a namespace in Postgres) for each graph. Let's see by examples.&lt;/p&gt;

&lt;p&gt;Run Postgres and load AGE (you'll find how to do that in the GitHub link above).&lt;/p&gt;

&lt;p&gt;First, create a graph:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;ag_catalog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create_graph&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'mygraph'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, run the command &lt;code&gt;\dn&lt;/code&gt; to print all schemas:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;test=# \dn
    List of schemas
    Name    |  Owner
------------+----------
 ag_catalog | rafsun42
 mygraph    | rafsun42
 public     | rafsun42
(3 rows)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can see AGE just created two schemas: &lt;code&gt;ag_catalog&lt;/code&gt; and &lt;code&gt;mygraph&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Besides using a schema for each graph, AGE uses one catalog schema, the &lt;code&gt;ag_catalog&lt;/code&gt;, to hold references (by means of schema name) to all AGE graphs created within the database.&lt;/p&gt;

&lt;p&gt;In the rest of the article, we will explore the tables within the &lt;code&gt;mygraph&lt;/code&gt; schema to understand AGE's graph data structure and performance.&lt;/p&gt;



&lt;h2&gt;
  
  
  Labels are tables
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Building the graph with Cypher
&lt;/h3&gt;

&lt;p&gt;Let's first build the graph by adding vertices and edges (AGE implements openCypher specification as its query language):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;ag_catalog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cypher&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'mygraph'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="err"&gt;$$&lt;/span&gt;
    &lt;span class="k"&gt;CREATE&lt;/span&gt; 
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prof&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Professor&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;degree&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'Bioloy'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'BIOL 1001'&lt;/span&gt;&lt;span class="p"&gt;}),&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prof&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;teach&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Teaches&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;day&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'Mon'&lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;RETURN&lt;/span&gt; &lt;span class="n"&gt;prof&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;teach&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt;
&lt;span class="err"&gt;$$&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prof&lt;/span&gt; &lt;span class="n"&gt;agtype&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;teach&lt;/span&gt; &lt;span class="n"&gt;agtype&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="n"&gt;agtype&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we created two vertices and a one-directional relation between them. Together, it represents that a professor teaches a biology class.&lt;/p&gt;

&lt;p&gt;Notice how Cypher works. All three entities have properties (looks like JSON objects) and variables (to be used in the RETURN clause). But, only the &lt;code&gt;prof&lt;/code&gt; vertex and the &lt;code&gt;teach&lt;/code&gt; edge have label (right after the colon).&lt;/p&gt;

&lt;h3&gt;
  
  
  Tables and their schemes
&lt;/h3&gt;

&lt;p&gt;Now, lets list the tables within the schema by running the commmand &lt;code&gt;\dt mygraph.*&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;test=# \dt mygraph.*
               List of relations
 Schema  |       Name       | Type  |  Owner
---------+------------------+-------+----------
 mygraph | Professor        | table | rafsun42
 mygraph | Teaches          | table | rafsun42
 mygraph | _ag_label_edge   | table | rafsun42
 mygraph | _ag_label_vertex | table | rafsun42
(4 rows)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, every label has its own table. Plus, two extra tables, called defaults, for entities with no label. Entities are stored in their respective label's table as a row.&lt;/p&gt;

&lt;p&gt;I encourage you to see the schema of the &lt;code&gt;Professor&lt;/code&gt; and &lt;code&gt;Teaches&lt;/code&gt; tables by running the following two command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;test=# \d mygraph."Professor" 
                Table "mygraph.Professor"
   Column   |  Type   | Collation | Nullable |     Default                                                       
------------+---------+-----------+----------+------------------
 id         | graphid |           | not null | ...
 properties | agtype  |           | not null | ...
Inherits: mygraph._ag_label_vertex


test=# \d mygraph."Teaches" 
                Table "mygraph.Teaches"
   Column   |  Type   | Collation | Nullable |      Default                                                     
------------+---------+-----------+----------+-------------------
 id         | graphid |           | not null | ...
 start_id   | graphid |           | not null | 
 end_id     | graphid |           | not null | 
 properties | agtype  |           | not null | ...
Inherits: mygraph._ag_label_edge
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why these two tables has different schema? Because one represents vertex label, and the other represents edge label. Edge entities require two additional attributes &lt;code&gt;start_id&lt;/code&gt; and &lt;code&gt;end_id&lt;/code&gt; to store the endpoints.&lt;/p&gt;



&lt;h2&gt;
  
  
  Performance
&lt;/h2&gt;

&lt;p&gt;I hope by now you understand how AGE stores graph and its entities in tables. Let's discuss why each label has separate table and how it affects performance.&lt;/p&gt;

&lt;p&gt;With this design, AGE takes advantage of partitioning with Postgres' inheritance feature. If you are not familiar with either partitioning or inheritance in Postgres, I recommend checking out my articles on these topic first.&lt;/p&gt;

&lt;p&gt;AGE puts all vertices in a single table at logical level and partition them by label at physical level. Notice the output of the &lt;code&gt;\d&lt;/code&gt; commands again. All vertex label tables inherit the default &lt;code&gt;_ag_label_vertex&lt;/code&gt; table, and all edge label tables inherit the default &lt;code&gt;_ag_label_edge&lt;/code&gt; table.&lt;/p&gt;

&lt;p&gt;When I mentioned before that &lt;code&gt;_ag_label_vertex&lt;/code&gt; contains only vertices with no label, it was true only at physical level. Each label's table has its own physical file on disk. However, at logical level, the default tables, like &lt;code&gt;_ag_label_vertex&lt;/code&gt;, is a table that contains all vertices. Because other vertex label tables are children of it. If you scan the &lt;code&gt;_ag_label_vertex&lt;/code&gt; table, Postgres will fetch all vertices unless you specify not to.&lt;/p&gt;

&lt;p&gt;Let's see how that helps in AGE's use cases. In a typical query, you would like to lookup some entities. Think about the two ways of looking up an entity in a graph (using Cypher):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cypher"&gt;&lt;code&gt;&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="n"&gt;Example&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="k"&gt;By&lt;/span&gt; &lt;span class="n"&gt;label&lt;/span&gt;
&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="n"&gt;Returns&lt;/span&gt; &lt;span class="ow"&gt;all&lt;/span&gt; &lt;span class="n"&gt;professors&lt;/span&gt;
&lt;span class="k"&gt;MATCH&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="py"&gt;x:&lt;/span&gt; &lt;span class="n"&gt;Professor&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt; &lt;span class="k"&gt;RETURN&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;

&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="n"&gt;Example&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="k"&gt;By&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;property&lt;/span&gt;
&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="n"&gt;Returns&lt;/span&gt; &lt;span class="ow"&gt;all&lt;/span&gt; &lt;span class="n"&gt;people&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;biology&lt;/span&gt;
&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="n"&gt;degree&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;could&lt;/span&gt; &lt;span class="n"&gt;be&lt;/span&gt; &lt;span class="n"&gt;anyone&lt;/span&gt;
&lt;span class="k"&gt;MATCH&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="ss"&gt;{&lt;/span&gt;&lt;span class="py"&gt;degree:&lt;/span&gt; &lt;span class="s1"&gt;'Biology'&lt;/span&gt;&lt;span class="ss"&gt;})&lt;/span&gt; &lt;span class="k"&gt;RETURN&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The performance of a lookup query greatly depends on how closely relevant data are stored on the physical disk. Since all rows of a relation are stored contiguously on disk, with this design, all nodes with same label will be put together in the same place. When executing the MATCH in the first example, all professor nodes can be fecthed to the main memory from the disk with minimum I\O calls.&lt;/p&gt;

&lt;p&gt;For the second example, we don't know the label. So we don't know which table to scan. Because of inheritance, we don't have to manually scan each vertex label table, instead we can only scan &lt;code&gt;_ag_label_vertex&lt;/code&gt; to look for any vertices regardless of its label. &lt;/p&gt;

&lt;p&gt;Overall, this approach makes matching by label faster, while keeping matching by properties simple.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;To summarize, each graph is a schema. Each label in a graph has its own table. For no-label entities, there are two default tables. All vertices and edges are stored in the respective table.&lt;/p&gt;

&lt;p&gt;As for performance, entities are put in the default table at logical level. But at physical level they are partioned by their label. As a result of partitioning, lookup query performance improves.&lt;/p&gt;

</description>
      <category>gratitude</category>
    </item>
  </channel>
</rss>
