Search code examples
orientdborientdb2.2

How to get last N connected edges


I'm writing a large scale chat application and here is my db schema:

CREATE CLASS User EXTENDS V;
CREATE PROPERTY User.name STRING;

CREATE CLASS Message EXTENDS V;
CREATE PROPERTY Message.text STRING;
CREATE PROPERTY Message.createdAt DATETIME;
CREATE INDEX Message.createdAt ON Message(createdAt) NOTUNIQUE;

CREATE CLASS Send EXTENDS E;

i'm using lightweight edges and i have 200,000 edges connected to #12:0 like this:

CREATE VERTEX User SET name = 'john';
/* #12:0 */

CREATE VERTEX Message SET content = 'Lorem ipsum dolor sit amet', createdAt = SYSDATE();
/* #20:0 */

CREATE EDGE Send FROM #12:0 TO #20:0

i want to get last 5 messages that connected to the #12:0. i tried these queries:

Query 1:

SELECT FROM (
  SELECT EXPAND(OUT('Send')) FROM #12:0
) ORDER BY createdAt DESC LIMIT 5

it took ~2s

"explain" result:

{
    "result": [
        {
            "@type": "d",
            "@version": 0,
            "documentReads": 200000,
            "current": "#19:66661",
            "recordReads": 200000,
            "fetchingFromTargetElapsed": 377,
            "expandElapsed": 0,
            "orderByElapsed": 5,
            "evaluated": 200000,
            "elapsed": 2416.7283,
            "resultType": "collection",
            "resultSize": 5,
            "@fieldTypes": "documentReads=l,current=x,recordReads=l,fetchingFromTargetElapsed=l,expandElapsed=l,orderByElapsed=l,evaluated=l,elapsed=f"
        }
    ],
    "notification": "Query executed in 2.427 sec. Returned 1 record(s)"
}

Query 2:

SELECT OUT('Send')[199994-199999] FROM #12:0

it took ~6s

"explain" result:

{
    "result": [
        {
            "@type": "d",
            "@version": 0,
            "documentReads": 1,
            "current": "#12:0",
            "recordReads": 1,
            "optimizationElapsed": 0,
            "fetchingFromTargetElapsed": 8749,
            "evaluated": 1,
            "elapsed": 8749.445,
            "resultType": "collection",
            "resultSize": 1,
            "@fieldTypes": "documentReads=l,current=x,recordReads=l,optimizationElapsed=l,fetchingFromTargetElapsed=l,evaluated=l,elapsed=f"
        }
    ],
    "notification": "Query executed in 8.759 sec. Returned 1 record(s)"
}

is there any faster way to do this?

please don't refer to the chat use case...

i'm using orientdb 2.2.7


Solution

  • Finally! i find a fast way to do this.

    I've change my db schema to:

    CREATE CLASS User EXTENDS V;
    CREATE PROPERTY User.name STRING;
    
    CREATE CLASS Message;
    CREATE PROPERTY Message.text STRING;
    CREATE PROPERTY Message.writer LINK User;
    CREATE PROPERTY Message.createdAt DATETIME;
    CREATE INDEX Message.writer ON Message(writer) NOTUNIQUE_HASH_INDEX;
    CREATE INDEX Message.createdAt ON Message(createdAt) NOTUNIQUE;
    

    I'm using Message.writer to connect to the User instead of using edge.

    Query:

    SELECT FROM Message
    WHERE createdAt < sysdate() AND writer = #12:0
    ORDER BY createdAt DESC
    SKIP 10 LIMIT 5
    

    this takes ~30ms on 1.5 million records!

    IMPORTANT: Notice the createdAt < sysdate() in WHERE clause, you have to write a dummy condition on the ORDER BY field, this makes ORDER BY to use createdAt index (~700ms faster)

    "explain" result (with createdAt < sysdate()):

    {
        "result": [
            {
                "@type": "d",
                "@version": 0,
                "documentReads": 252,
                "fullySortedByIndex": true,
                "documentAnalyzedCompatibleClass": 252,
                "recordReads": 252,
                "fetchingFromTargetElapsed": 6,
                "indexIsUsedInOrderBy": true,
                "compositeIndexUsed": 1,
                "current": "#49:1493348",
                "involvedIndexes": [
                    "Message.createdAt"
                ],
                "limit": 5,
                "evaluated": 252,
                "elapsed": 6.447579,
                "resultType": "collection",
                "resultSize": 5,
                "@fieldTypes": "documentReads=l,documentAnalyzedCompatibleClass=l,recordReads=l,fetchingFromTargetElapsed=l,compositeIndexUsed=l,current=x,involvedIndexes=e,evaluated=l,user=x,elapsed=f"
            }
        ],
        "notification": "Query executed in 0.032 sec. Returned 1 record(s)"
    }
    

    "explain" result (without createdAt < sysdate()):

    {
        "result": [
            {
                "@type": "d",
                "@version": 0,
                "documentReads": 48512,
                "fullySortedByIndex": false,
                "documentAnalyzedCompatibleClass": 48512,
                "recordReads": 48512,
                "fetchingFromTargetElapsed": 801,
                "indexIsUsedInOrderBy": false,
                "compositeIndexUsed": 1,
                "current": "#49:1499971",
                "involvedIndexes": [
                    "Message.writer"
                ],
                "limit": 5,
                "orderByElapsed": 49,
                "evaluated": 48512,
                "elapsed": 853.48004,
                "resultType": "collection",
                "resultSize": 5,
                "@fieldTypes": "documentReads=l,documentAnalyzedCompatibleClass=l,recordReads=l,fetchingFromTargetElapsed=l,compositeIndexUsed=l,current=x,involvedIndexes=e,orderByElapsed=l,evaluated=l,user=x,elapsed=f"
            }
        ],
        "notification": "Query executed in 0.864 sec. Returned 1 record(s)"
    }