3

現在、古い Neo4j 関連のコードを新しい Neo4j 2.0.0 ベータ版に移行しています。新しいスキーマ インデックスはさまざまな場合に便利な機能だと思うので、可能であればコードを変更してそれらを使用したいと考えました。でもそうする前に、パフォーマンスが落ちないようにしたいと思っていました。だから私は小さなテストを書きました。そして驚くべきことに、ルックアップに関しては、スキーマ インデックスは一貫して従来のインデックスよりもパフォーマンスが低下します。しかし、結論に飛びつく前に、私のテストをあなたと共有したいと思います。そうすれば、私が違法なことをしたのか、それともテストケースの単純さまたは同様の問題のために結果がこのようになったのかを教えてください. また、自分で試してみて、私の観察を確認/拒否することもできます。現状では、従来のインデックスに固執したいので、

私のコードの下。1 つのタイプのインデックス (レガシーまたはスキーマ) への呼び出しをコメント アウトしてテストし、全体を数回実行しました。ここに示すように 1000 から 60000 までの範囲の N のさまざまな値で試してみましたが、従来のインデックスが大幅に高速なルックアップを行うという相対的な結果は常に同じでした。明らかに、私のユースケースは多数のノードであり、それぞれに一意の ID があり、ノードの ID しか持っていないノードの範囲全体をできるだけ迅速に検索する必要があります。

私の質問は次のとおりです: レガシー インデックスは実際に高速ですか? これが私にとって大きな問題である場合、または何か間違ったことをしている場合、またはこれが既知の問題であり、ベータ中に解決され、リリースで解決される場合は、それらに固執する必要がありますか? ありがとうございました!

import java.io.File;
import java.io.IOException;
import java.util.concurrent.TimeUnit;

import org.apache.commons.io.FileUtils;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Label;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.ResourceIterator;
import org.neo4j.graphdb.Transaction;
import org.neo4j.graphdb.factory.GraphDatabaseFactory;
import org.neo4j.graphdb.index.Index;
import org.neo4j.graphdb.schema.IndexDefinition;
import org.neo4j.graphdb.schema.Schema;
import org.neo4j.tooling.GlobalGraphOperations;

enum labels implements Label {
    term
}

public class Neo4jIndexPerformanceTest {
    private static int N = 1000;

    public static void main(String[] args) throws IOException {
        FileUtils.deleteDirectory(new File("tmp/graph.db"));
        GraphDatabaseService graphDb = new GraphDatabaseFactory().newEmbeddedDatabase("tmp/graph.db");
        try (Transaction tx = graphDb.beginTx()) {
            int i = 0;
            for (Node n : GlobalGraphOperations.at(graphDb).getAllNodes())
                i++;
            System.out.println("Number of nodes: " + i);
        }
//      createLegacyIndex(graphDb);
//      searchLegacyIndex(graphDb);
        createSchemaIndex(graphDb);
        searchSchemaIndex(graphDb);
        graphDb.shutdown();
    }

    private static void searchSchemaIndex(GraphDatabaseService graphDb) {
        try (Transaction tx = graphDb.beginTx()) {
            IndexDefinition index = graphDb.schema().getIndexes(labels.term).iterator().next();
            graphDb.schema().awaitIndexOnline(index, 10, TimeUnit.SECONDS);
        }
        long time = System.currentTimeMillis();
        try (Transaction tx = graphDb.beginTx()) {
            for (int i = 0; i < N; i++) {
                ResourceIterator<Node> iterator = graphDb.findNodesByLabelAndProperty(labels.term, "id", "schema:" + i).iterator();
                if (iterator.hasNext()) {
                    Node n = iterator.next();
                } 
                iterator.close();
            }
        }
        time = System.currentTimeMillis() - time;
        System.out.println("Searching schema index took: " + time + " ms");
    }

    private static void searchLegacyIndex(GraphDatabaseService graphDb) {
        long time = System.currentTimeMillis();
        try (Transaction tx = graphDb.beginTx()) {
            Index<Node> index = graphDb.index().forNodes("terms");
            for (int i = 0; i < N; i++) {
                ResourceIterator<Node> iterator = index.get("id", "legacy:" + i).iterator();
                if (iterator.hasNext()) {
                    Node single = iterator.next();
                }
                iterator.close();
                // if (single == null)
                // throw new IllegalStateException();
            }
        }
        time = System.currentTimeMillis() - time;
        System.out.println("Searching legacy index took: " + time + " ms");

    }

    private static void createSchemaIndex(GraphDatabaseService graphDb) {
        Schema schema = null;
        try (Transaction tx = graphDb.beginTx()) {
            schema = graphDb.schema();
            boolean e = false;
            for (IndexDefinition id : graphDb.schema().getIndexes()) {
                e = true;
            }
            if (!e)
                schema.indexFor(labels.term).on("id").create();
            tx.success();
        }
        try (Transaction tx = graphDb.beginTx()) {
            long time = System.currentTimeMillis();

            for (int i = 0; i < N; i++) {
                Node n = graphDb.createNode(labels.term);
                n.setProperty("id", "schema:" + i);
            }

            time = System.currentTimeMillis() - time;
            schema.awaitIndexesOnline(10, TimeUnit.SECONDS);
            tx.success();
            System.out.println("Creating schema index took: " + time + " ms");
        }
    }

    private static void createLegacyIndex(GraphDatabaseService graphDb) {
        try (Transaction tx = graphDb.beginTx()) {
            Index<Node> index = graphDb.index().forNodes("terms");

            long time = System.currentTimeMillis();

            for (int i = 0; i < N; i++) {
                Node n = graphDb.createNode(labels.term);
                n.setProperty("id", "legacy:" + i);
                index.add(n, "id", n.getProperty("id"));
            }

            time = System.currentTimeMillis() - time;
            tx.success();
            System.out.println("Creating legacy index took: " + time + " ms");
        }
    }
}
4

1 に答える 1

3

私はあなたのコードを試しましたが、実際にスキーマ インデックスの実装はレガシーほど高速ではありません。しかし、私はその理由を見つけました。これは、インデックス自体ではなく、インデックス周辺の実装における単純な間違いです。私はローカルでこれらの間違いを修正しようとしましたが、それらはレガシー インデックスとスキーマ インデックスとまったく同じパフォーマンスです。

したがって、適切な修正を行うことが問題であり、それが 2.0 リリースに組み込まれることを願うばかりです。

于 2013-11-17T23:53:40.407 に答える