Secondary index creation only seems to work once


#1

Hi.

Using the java client I have a small test program which creates 10.000 records in a set, with a secondary index integer entry. I create the secondary index when I first connect to the database and this works fine.

However if I run the test a second time using a new set name and use the same code to create a new scondary index on the new set, I see no errors on createIndex, but when I try to use the index I get a 201 error that the index does not exist. I can also see in the sindex.smd file that the new secondary index has not been created. I create the index after I have added the data.

Is my understanding correct that secondary indices can be added dynamically, as new sets are added to a running database?


#2

Using aql creation of a new secondary index on a new set is successful


#3

this is my small test program. Run this on a newly created database (.dat file) with ‘set1’ as args[0] and it creates an index on the set set1. Run again using set2 and it fails to create the index. Could this be because the index I am creating has the same name for each set? public class AeroSpikePersistenceManagerTester {

private AerospikeClient client;
private String namespace;
private ClientPolicy policy;
private int port;
private String server;

public static void main(String[] args) {

	String setToCreate = null;

	if (args.length >= 1) {

		setToCreate = args[0];

	}

	if (setToCreate != null) {

		AeroSpikePersistenceManagerTester aeroSpikePersistenceManagerTester;

		try {

			aeroSpikePersistenceManagerTester = new AeroSpikePersistenceManagerTester();

			aeroSpikePersistenceManagerTester.runStringPersistenceTest(setToCreate);

		} catch (Throwable e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

}

private void runStringPersistenceTest(String setToCreate) {

	try {

		int entriesToProcess = 10000;

		long startPutTime = System.currentTimeMillis();

		IndexTask secondaryIndexStringTask = this.getClient().createIndex(null, this.getNamespace(), setToCreate,
				"idxSecondaryIndexStr", "idxSecIDXSTR", IndexType.STRING);

		secondaryIndexStringTask.waitTillComplete();

		String secIndexInfo = Info.request(this.getClient().getInfoPolicyDefault(), this.getClient().getNodes()[0], "sindex");

		System.out.println("gotcha " + secIndexInfo);

		if (!secIndexInfo.contains(setToCreate)) {

			System.out.println("sec index " + setToCreate + " is missing");

		} else {

			System.out.println("sec index " + setToCreate + " is present");

		}

		for (int i = 0; i < entriesToProcess; i++) {

			Key key = new Key(this.getNamespace(), setToCreate, "value-" + i);

			Bin bin = new Bin(null, new String("value-" + i));

			Bin secIdxBinStr = new Bin("idxSecIDXSTR", "value-" + i);

			// Bin secIdxBinInt = new Bin("idxSecIDXINT", i);

			this.getClient().put(this.getPolicy().writePolicyDefault, key, bin, secIdxBinStr);

			if ((i + 1) % 5000 == 0) {

				System.out.println("Added " + (i + 1) + " entries");

			}

		}

		long endPutTime = System.currentTimeMillis();

		long elapsedPutTime = endPutTime - startPutTime;

		System.out.println("put " + entriesToProcess + " strings in " + elapsedPutTime + " milliseconds");

		double milliSecsPerPut = (double) elapsedPutTime / (double) entriesToProcess;

		System.out.println("millis-secs per put: " + milliSecsPerPut);

		double putsPerSecond = 1000.0 / milliSecsPerPut;

		System.out.println("Puts Per Second: " + (int) putsPerSecond);

		long startGetTime = System.currentTimeMillis();

		for (int i = 0; i < entriesToProcess; i++) {

			Key key = new Key(this.getNamespace(), setToCreate, "value-" + i);

			@SuppressWarnings("unused")
			Record record = this.getClient().get(this.getPolicy().readPolicyDefault, key);

			if ((i + 1) % 5000 == 0) {

				System.out.println("Retrieved " + (i + 1) + " entries");

			}

		}

		long endGetTime = System.currentTimeMillis();

		long elapsedGetTime = endGetTime - startGetTime;

		System.out.println("got " + entriesToProcess + " strings in " + elapsedGetTime + " milliseconds");

		double milliSecsPerGet = (double) elapsedGetTime / (double) entriesToProcess;

		System.out.println("millis-secs per get: " + milliSecsPerGet);

		double getsPerSecond = 1000.0 / milliSecsPerGet;

		System.out.println("Gets Per Second: " + (int) getsPerSecond);

	} catch (Throwable t) {

		t.printStackTrace();

	}

}

public AeroSpikePersistenceManagerTester() throws Throwable {

	String aeroSpikeNamespace = "nalytics";

	String aerospikeServer = "192.168.56.101";

	int aerospikePortInt = 3000;

	this.namespace = aeroSpikeNamespace;
	this.server = aerospikeServer;
	this.port = aerospikePortInt;

	this.policy = new ClientPolicy();

}

private AerospikeClient getClient() {

	if (this.client == null) {

		Host[] hosts = Host.parseHosts(this.getServer(), this.getPort());

		this.client = new AerospikeClient(policy, hosts);

	}

	return this.client;

}

private String getNamespace() {
	return namespace;
}

private ClientPolicy getPolicy() {
	return policy;
}

private int getPort() {
	return port;
}

private String getServer() {
	return server;
}

#4

Solved this one. In case anyone else runs into the same issue; the indexName argument to createIndex must be unique. I was using the same index name as I was assuming that this would be qualified by the set name (which was a different new set each time). So index names must be unique across sets, not simply within sets.


#5

Thanks for posting the solution. This was the first thing that came to my mind, but you did figure it out. You should have gotten an error when trying to create the index with the same name the second time, though.


#6

Thanks for the reply. Definitely no exception thrown when creating index with a name that already exists.


#7

I stand corrected… The server will return an error (and likely have a warning in the logs) but it seems the client will treat it as a success. I can see this both ways, but personally feels it should be reported as an error.