3636import org .polypheny .simpleclient .query .QueryListEntry ;
3737import org .polypheny .simpleclient .query .RawQuery ;
3838import org .polypheny .simpleclient .scenario .PolyphenyScenario ;
39+ import org .polypheny .simpleclient .scenario .vectorbench .queryBuilder .postgres .ddl .PgCreateBooleanFeature ;
40+ import org .polypheny .simpleclient .scenario .vectorbench .queryBuilder .postgres .ddl .PgCreateBooleanFeatureIndex ;
3941import org .polypheny .simpleclient .scenario .vectorbench .queryBuilder .postgres .ddl .PgCreateRealFeature ;
4042import org .polypheny .simpleclient .scenario .vectorbench .queryBuilder .postgres .ddl .PgCreateRealFeatureIndex ;
43+ import org .polypheny .simpleclient .scenario .vectorbench .queryBuilder .postgres .dql .PgSimpleKnnBooleanFeature ;
44+ import org .polypheny .simpleclient .scenario .vectorbench .queryBuilder .postgres .dql .PgSimpleKnnBooleanFeatureFiltered ;
45+ import org .polypheny .simpleclient .scenario .vectorbench .queryBuilder .postgres .dql .PgSimpleKnnIdRealFeature ;
46+ import org .polypheny .simpleclient .scenario .vectorbench .queryBuilder .postgres .dql .PgSimpleKnnRealCrossJoin ;
4147import org .polypheny .simpleclient .scenario .vectorbench .queryBuilder .postgres .dql .PgSimpleKnnRealFeature ;
4248import org .polypheny .simpleclient .scenario .vectorbench .queryBuilder .postgres .dql .PgSimpleKnnRealFeatureFiltered ;
4349import java .io .File ;
@@ -69,6 +75,7 @@ public void createSchema( DatabaseInstance databaseInstance, boolean includingKe
6975 executor = executorFactory .createExecutorInstance ();
7076 executor .executeQuery ( new RawQuery ( "CREATE EXTENSION IF NOT EXISTS vector" , null , false ) );
7177 executor .executeQuery ( new PgCreateRealFeature ( config .dimensionFeatureVectors ).getNewQuery () );
78+ executor .executeQuery ( new PgCreateBooleanFeature ( config .dimensionFeatureVectors ).getNewQuery () );
7279 } catch ( ExecutorException e ) {
7380 throw new RuntimeException ( "Exception while creating schema" , e );
7481 } finally {
@@ -85,10 +92,19 @@ public void createIndex() {
8592 try {
8693 executor = executorFactory .createExecutorInstance ();
8794 long start = System .nanoTime ();
88- executor .executeQuery ( new PgCreateRealFeatureIndex ( config .indexMethod , config .distanceNorm , config .indexM , config .indexEfConstruction , config .indexLists ).getNewQuery () );
95+ if ( indexSupportsMetric ( config .indexMethod , config .distanceNorm ) ) {
96+ executor .executeQuery ( new PgCreateRealFeatureIndex ( config .indexMethod , config .distanceNorm , config .indexM , config .indexEfConstruction , config .indexLists ).getNewQuery () );
97+ } else {
98+ log .info ( "Skipping real index: {} does not support metric '{}'." , config .indexMethod , config .distanceNorm );
99+ }
100+ if ( indexSupportsMetric ( config .indexMethod , config .booleanDistanceNorm ) ) {
101+ executor .executeQuery ( new PgCreateBooleanFeatureIndex ( config .indexMethod , config .booleanDistanceNorm , config .indexM , config .indexEfConstruction , config .indexLists ).getNewQuery () );
102+ } else {
103+ log .info ( "Skipping boolean index: {} does not support metric '{}'." , config .indexMethod , config .booleanDistanceNorm );
104+ }
89105 executor .executeCommit ();
90106 long durationMillis = ( System .nanoTime () - start ) / 1_000_000L ;
91- log .info ( "Vector index built in {} ms" , durationMillis );
107+ log .info ( "Vector indexes built in {} ms" , durationMillis );
92108
93109 String conf = config .indexMethod .equals ( "hnsw" )
94110 ? "hnsw.ef_search = " + config .queryEfSearch
@@ -111,6 +127,7 @@ public void generateData( DatabaseInstance databaseInstance, ProgressReporter pr
111127 PgDataGenerator dataGenerator = new PgDataGenerator ( executor , config , progressReporter );
112128 try {
113129 dataGenerator .generateRealFeatures ();
130+ dataGenerator .generateBooleanFeatures ();
114131 } catch ( ExecutorException e ) {
115132 throw new RuntimeException ( "Exception while generating data" , e );
116133 } finally {
@@ -130,6 +147,11 @@ public long execute( ProgressReporter progressReporter, CsvWriter csvWriter, Fil
130147 List <QueryListEntry > queryList = new Vector <>();
131148 addNumberOfTimes ( queryList , new PgSimpleKnnRealFeature ( config .randomSeedQuery , config .dimensionFeatureVectors , config .limitKnnQueries , config .distanceNorm ), config .numberOfSimpleKnnRealFeatureQueries );
132149 addNumberOfTimes ( queryList , new PgSimpleKnnRealFeatureFiltered ( config .randomSeedQuery , config .dimensionFeatureVectors , config .limitKnnQueries , config .distanceNorm , "cat_A" ), config .numberOfSimpleKnnRealFeatureFilteredQueries );
150+ addNumberOfTimes ( queryList , new PgSimpleKnnIdRealFeature ( config .randomSeedQuery , config .dimensionFeatureVectors , config .limitKnnQueries , config .distanceNorm ), config .numberOfSimpleKnnIdRealFeatureQueries );
151+ addNumberOfTimes ( queryList , new PgSimpleKnnRealCrossJoin ( config .randomSeedQuery , config .dimensionFeatureVectors , config .limitKnnQueries , config .distanceNorm ), config .numberOfSimpleKnnRealCrossJoinQueries );
152+ addNumberOfTimes ( queryList , new PgSimpleKnnBooleanFeature ( config .randomSeedQuery , config .dimensionFeatureVectors , config .limitKnnQueries , config .booleanDistanceNorm ), config .numberOfSimpleKnnBooleanFeatureQueries );
153+ addNumberOfTimes ( queryList , new PgSimpleKnnBooleanFeatureFiltered ( config .randomSeedQuery , config .dimensionFeatureVectors , config .limitKnnQueries , config .booleanDistanceNorm , "cat_A" ), config .numberOfSimpleKnnBooleanFeatureFilteredQueries );
154+
133155 return commonExecute ( queryList , progressReporter , outputDirectory , numberOfThreads ,
134156 Query ::getSql , () -> executorFactory .createExecutorInstance ( csvWriter ), new Random () );
135157 }
@@ -138,14 +160,36 @@ public long execute( ProgressReporter progressReporter, CsvWriter csvWriter, Fil
138160 @ Override
139161 public void warmUp ( ProgressReporter progressReporter ) {
140162 log .info ( "Warm-up..." );
141- PgSimpleKnnRealFeature knnBuilder = new PgSimpleKnnRealFeature ( config .randomSeedQuery , config .dimensionFeatureVectors , config .limitKnnQueries , config .distanceNorm );
142163 Executor executor = null ;
164+ PgSimpleKnnRealFeature pgSimpleKnnRealFeature = new PgSimpleKnnRealFeature ( config .randomSeedQuery , config .dimensionFeatureVectors , config .limitKnnQueries , config .distanceNorm );
165+ PgSimpleKnnRealFeatureFiltered pgSimpleKnnRealFeatureFiltered = new PgSimpleKnnRealFeatureFiltered ( config .randomSeedQuery , config .dimensionFeatureVectors , config .limitKnnQueries , config .distanceNorm , "cat_A" );
166+ PgSimpleKnnRealCrossJoin pgSimpleKnnRealCrossJoin = new PgSimpleKnnRealCrossJoin ( config .randomSeedQuery , config .dimensionFeatureVectors , config .limitKnnQueries , config .distanceNorm );
167+ PgSimpleKnnIdRealFeature pgSimpleKnnIdRealFeature = new PgSimpleKnnIdRealFeature ( config .randomSeedQuery , config .dimensionFeatureVectors , config .limitKnnQueries , config .distanceNorm );
168+ PgSimpleKnnBooleanFeature pgSimpleKnnBooleanFeature = new PgSimpleKnnBooleanFeature ( config .randomSeedQuery , config .dimensionFeatureVectors , config .limitKnnQueries , config .booleanDistanceNorm );
169+ PgSimpleKnnBooleanFeatureFiltered pgSimpleKnnBooleanFeatureFiltered = new PgSimpleKnnBooleanFeatureFiltered ( config .randomSeedQuery , config .dimensionFeatureVectors , config .limitKnnQueries , config .booleanDistanceNorm , "cat_A" );
170+
143171 for ( int i = 0 ; i < config .numberOfWarmUpIterations ; i ++ ) {
144172 try {
145173 executor = executorFactory .createExecutorInstance ();
146174 if ( config .numberOfSimpleKnnRealFeatureQueries > 0 ) {
147- executor .executeQuery ( knnBuilder .getNewQuery () );
175+ executor .executeQuery ( pgSimpleKnnRealFeature .getNewQuery () );
176+ }
177+ if ( config .numberOfSimpleKnnRealFeatureFilteredQueries > 0 ) {
178+ executor .executeQuery ( pgSimpleKnnRealFeatureFiltered .getNewQuery () );
179+ }
180+ if ( config .numberOfSimpleKnnRealCrossJoinQueries > 0 ) {
181+ executor .executeQuery ( pgSimpleKnnRealCrossJoin .getNewQuery () );
182+ }
183+ if ( config .numberOfSimpleKnnIdRealFeatureQueries > 0 ) {
184+ executor .executeQuery ( pgSimpleKnnIdRealFeature .getNewQuery () );
148185 }
186+ if ( config .numberOfSimpleKnnBooleanFeatureQueries > 0 ) {
187+ executor .executeQuery ( pgSimpleKnnBooleanFeature .getNewQuery () );
188+ }
189+ if ( config .numberOfSimpleKnnBooleanFeatureFilteredQueries > 0 ) {
190+ executor .executeQuery ( pgSimpleKnnBooleanFeatureFiltered .getNewQuery () );
191+ }
192+
149193 } catch ( ExecutorException e ) {
150194 throw new RuntimeException ( "Error during warm-up" , e );
151195 } finally {
@@ -166,6 +210,15 @@ public int getNumberOfInsertThreads() {
166210 }
167211
168212
213+ private static boolean indexSupportsMetric ( String method , String metric ) {
214+ // HNSW supports all metrics; IVFFlat does not support L1 or JACCARD.
215+ if ( method .equalsIgnoreCase ( "ivfflat" ) ) {
216+ return !( metric .equalsIgnoreCase ( "L1" ) || metric .equalsIgnoreCase ( "JACCARD" ) );
217+ }
218+ return true ;
219+ }
220+
221+
169222 private void addNumberOfTimes ( List <QueryListEntry > list , QueryBuilder builder , int count ) {
170223 int id = queryTypes .size () + 1 ;
171224 queryTypes .put ( id , builder .getNewQuery ().getSql () );
0 commit comments