Skip to content

Add DatabaseClient bind variant for list of positioned parameters #33274

@wanyongx

Description

@wanyongx

https://github.com/spring-projects/spring-framework/blob/65faca8236124e0ae37ff68afc2366f7ccf286d2/spring-r2dbc/src/main/java/org/springframework/r2dbc/core/DefaultDatabaseClient.java#L264C2-L274C4

these bind methods new too many times when many binds.

@Override
public DefaultGenericExecuteSpec bind(int index, Object value) {
	assertNotPreparedOperation();
	Assert.notNull(value, () -> String.format(
			"Value at index %d must not be null. Use bindNull(…) instead.", index));

	Map<Integer, Parameter> byIndex = new LinkedHashMap<>(this.byIndex);
	byIndex.put(index, resolveParameter(value));

	return new DefaultGenericExecuteSpec(byIndex, this.byName, this.sqlSupplier, this.filterFunction);
}

A batch interface can be provided or some optimize so that the following two objects can be created only once

new LinkedHashMap<>   
new DefaultGenericExecuteSpec

I do a test to check the performance:

        @Test
	public void test() {
		DefaultGenericExecuteSpec spec = new DefaultGenericExecuteSpec(() -> "select 1");

		long start = System.currentTimeMillis();
		for (int i = 0; i < 10000; i++){
			// use the default method
			spec = spec.bind(i, "string");
		}
		System.out.println("default method cost: " + (System.currentTimeMillis() - start));

		start = System.currentTimeMillis();
		for (int i = 0; i < 10000; i++){
			// use the optimized method
			spec = spec.bind2(i, "string");
		}
		System.out.println("optimized method cost: " + (System.currentTimeMillis() - start));
	}


        public DefaultGenericExecuteSpec bind2(int index, Object value) {
			assertNotPreparedOperation();
			Assert.notNull(value, () -> String.format(
					"Value at index %d must not be null. Use bindNull(…) instead.", index));
			if(byIndex.isEmpty()) {
				Map<Integer, Parameter> byIndex = new LinkedHashMap<>(this.byIndex);
				byIndex.put(index, resolveParameter(value));

				return new DefaultGenericExecuteSpec(byIndex, this.byName, this.sqlSupplier, this.filterFunction);
			}

			byIndex.put(index, resolveParameter(value));
			return this;
		}

the result is

default method cost: 1790
optimized method cost: 5

more details, my project need insert large amount of data , about 3000 bind parameters per second. The cpu is high. I analyze to here according to the flame diagram.
image

Metadata

Metadata

Assignees

Labels

in: dataIssues in data modules (jdbc, orm, oxm, tx)type: enhancementA general enhancement

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions