Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
214 views
in Technique[技术] by (71.8m points)

Spring Boot neo4j performance

we are evaluating in our company the possibilities with neo4j, we are using Java (>1.8), Spring Boot (2.4.2) and SpringData-neo4j (2.4.2) to make simple queries and some performance tests, neo4j is running locally in a docker container using the official docker image.

This is our setup:

the json structure

{
    "id": null,
    "addresses": [
      {
        "id": null,
        "city": "South Thresa",
        "country": "Burundi",
        "houseNumber": "861",
        "street": "Auer Lake",
        "zipCode": "03412"
      }
    ],
    "bankAccounts": [
      {
        "id": null,
        "bankAccountNumber": null,
        "bankName": null,
        "bic": "QVWPKO5H",
        "blz": null,
        "countryCode": null,
        "divergentAccountHolder": null,
        "iban": "GB87DPZP84667918216002",
        "sepaMandates": [
          {
            "id": null,
            "bankAccount": null,
            "signatureCity": "Lednerbury",
            "signatureDate": "06.10.1984"
          }
        ]
      }
    ],
    "contacts": [
      {
        "id": null,
        "email": "[email protected]",
        "faxNumber": "087-835-0885 x859",
        "mobilePhoneNumber": "1-615-772-6922",
        "phoneNumber": "(082) 785-8108 x6736"
      }
    ],
    "birthDate": "07.01.1966",
    "firstName": "Daniel",
    "lastName": "Hartmann",
    "salutation": "Mrs.",
    "title": "Lead Branding Orchestrator"
  }

Entities:

@Node
public class Partner {
    @Id
    @GeneratedValue
    public Long id;
    @Relationship(type = "ADDRESS", direction = Relationship.Direction.INCOMING)
    public List<Address> addresses;
    @Relationship(type = "BANKACCOUNT", direction = Relationship.Direction.INCOMING)
    public List<BankAccount> bankAccounts;
    @Relationship(type = "CONTACTS", direction = Relationship.Direction.INCOMING)
    public List<Contact> contacts;
    @Property
    public String birthDate;
    @Property
    public String firstName;
    @Property
    public String lastName;
    @Property
    public String salutation;
    @Property
    public String title;
}

@Node
public class Contact{
    @Id
    @GeneratedValue
    public Long id;
    @Property
    public String email;
    @Property
    public String faxNumber;
    @Property
    public String mobilePhoneNumber;
    @Property
    public String phoneNumber;

@Node
public class BankAccount{
    @Id
    @GeneratedValue
    public Long id;
    @Property
    public String bankAccountNumber;
    @Property
    public String bankName;
    @Property
    public String bic;
    @Property
    public String blz;
    @Property
    public String countryCode;
    @Property
    public String divergentAccountHolder;
    @Property
    public String iban;
    @Relationship(type = "SEPA_MANDAT")
    public List<SepaMandate> sepaMandates;

@Node
public class Address{
    @Id
    @GeneratedValue
    public Long id;
    @Property
    public String city;
    @Property
    public String country;
    @Property
    public String houseNumber;
    @Property
    public String street;
    @Property
    public String zipCode;

@Node
public class SepaMandate{
    @Id
    @GeneratedValue
    public Long id;
    @Property
    public BankAccount bankAccount;
    @Property
    public String signatureCity;
    @Property
    public String signatureDate;

Repository:

public interface PartnerRepository extends Neo4jRepository<Partner, Long> {
  List<Partner> findByLastName(String name);
}

The controller has a endpoint to trigger a massinsert and stops the time

    @PutMapping("/partner/initialInsert")
    public void createPartner() {
        List<Partner> partners = mockData();
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        partnerRepository.saveAll(partners);
        stopWatch.stop();
        System.err.println("Created: 100000 partnerEntries  ---->>> Duration ------------> " + stopWatch.toString());
    }

And some simple query/update and insert endpoints

    @GetMapping("/partner")
    public List<Partner> getPartnerByLastName(@RequestParam(value = "lastname") String lastname) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        List<Partner> partners = partnerRepository.findByLastName(lastname);
        stopWatch.stop();
        System.err.println("Selecting partners by lastname: " +lastname + " took: " + stopWatch.toString() + " and returns: " + partners.size() + " partners");
        return partners;
    }

    @PutMapping("/partner")
    public void createPartner(@RequestBody Partner partner) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        partnerRepository.save(partner);
        stopWatch.stop();
        System.err.println("Updating/Inserting partner took: " + stopWatch.toString());
    }

    @PostMapping("/partner/bulk")
    public void bulkUpdatePartner(@RequestBody List<Partner> partners) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        partnerRepository.saveAll(partners);
        stopWatch.stop();
        System.err.println("Updating/Inserting partner took: " + stopWatch.toString());
    }

Here are our test results:

Inserting random data using which inserts via bulk saveAll().

  • Created: 1000 partnerEntries ---->>> Duration ------> 00:00:29.775
  • Created: 10000 partnerEntries ---->>> Duration ------> 00:04:40.259
  • Created: 100000 partnerEntries ---->>> Duration ------> 00:53:48.862

Selecting data via lastname severals times

  • Selecting partners by lastname: Borer took: 00:00:00.404 and returns: 257 partners
  • Selecting partners by lastname: Borer took: 00:00:00.219 and returns: 257 partners
  • Selecting partners by lastname: Borer took: 00:00:00.173 and returns: 257 partners
  • Selecting partners by lastname: Borer took: 00:00:00.239 and returns: 257 partners
  • Selecting partners by lastname: Borer took: 00:00:00.194 and returns: 257 partners
  • Selecting partners by lastname: Borer took: 00:00:00.266 and returns: 257 partners

Updating/Inserting a single entry:

  • Updating partner took: 00:00:00.297
  • Inserting partner took: 00:00:00.124

Update bulk 256 partners using jpa:

  • Updating partner took: 00:00:08.931

Update bulk 256 partner using Session-Object without jpa:

  • Updating partner took: 00:00:00.090

We are really curious about that the mass-insert with the jpa function saveAll() is taking > 50min for inserting 100.000 objects and difference between updating 256 entries via jpa and the session-Object. Now the question, are we doing something wrong, we tried to use a simple setup without any specialcases, is there a problem with the spring-data integration or do you guys have simular problems? I'm looking forward to here your experiences with neo4j :-)

Greets Dan :)

P.S: this is how we update with the session object

try (Session session = driver.session()) {
            session.run("MATCH (a:Partner {lastName: 'Borer'}) SET a.firstName = '" + firstname + "'");
}
question from:https://stackoverflow.com/questions/65903344/spring-boot-neo4j-performance

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)
Waitting for answers

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...