The model (as is evident from the query) is a group of TlD nodes (such as Tld{tld:"com"}) attached via a :root relationship to Domain nodes (such as Domain{domain:"foo", subdomain:"www"}) which are attached to Ip nodes (such as `Ip{address:"1.1.1.1"}.
Here are the explain and profile png's for single inserts:
If it helps here's the golang code I'm using to generate the query: MapResults converts the result structs into a generic map structure to satisfy the tx.Run method.
Look at the beginning of the two branches that are orange. It indicates each starts with a node label scan, I,e, it is scanning all nodes with the label to filter on the predicate in the next stage. Looks like the are lots of nodes for these two labels. You may want to try adding an index to those two labels and corresponding properties.
From the profile it does not appear you have any indexes to support the Merge statements. Since a MERGE is effectively a create or update, if it is to do an update than having an index will improve the performance.
For performance reasons, creating a schema index on the label or property is highly recommended when using MERGE. See Indexes for search performance for more information.
Ended up going with unique constraints on Tld, Ip, and Domain (using a domainkey field which is a concat of root and subdomain) and now the batch insert finishes in ~10 secs which is fine!
nope apparently this didn't fix it. Example input:
PROFILE
UNWIND {tld:"com", Domain:"test2",address:"1.2.37.4",Subdomain:"test2", Domainkey: "test2.test2",Rdn:"luz", Port:443} as row
Merge (tld:Tld{tld:row.tld})
Merge (ip:Ip{address:row.address})
ON CREATE SET ip.rdn = row.Rdn SET ip.port = row.Port
Merge (domain:Domain{domainkey:row.Domainkey})
ON CREATE SET domain.domain = row.Domain, domain.subdomain = row.Subdomain
Merge (domain)-[:tld]->(tld)
Merge (domain)<-[:host]-(ip)
47 seconds to enter one row. Is it because the relationships are anonymous? It's using all the unique index lookups I've created so it doesn't seem to be the lookup that's the issue.
Just a note and I doubt this is the cause, but on your ip merge you are setting the ‘ip’ and ‘rdn’ attributes in separate SET clauses. You can see in the profile that the second SET is separate and always done separately from the first. It is not associated with the MERGE clause. Did you mean the following instead:
ON CREATE SET ip.rdn = row.Rdn, ip.port = row.Port