Skip to content

Commit

Permalink
Add SkipSmallIndexesPredicate (#493)
Browse files Browse the repository at this point in the history
* Add SkipSmallIndexesPredicate

* Fix checkstyle

* Fix test
  • Loading branch information
mfvanek authored Nov 15, 2024
1 parent 8029a92 commit 3b65e9c
Show file tree
Hide file tree
Showing 9 changed files with 145 additions and 10 deletions.
2 changes: 1 addition & 1 deletion config/checkstyle/checkstyle.xml
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@
<!-- <module name="InterfaceMemberImpliedModifier"/> invalid -->
<module name="JavaNCSS"/>
<module name="LambdaBodyLength">
<property name="max" value="30"/>
<property name="max" value="35"/>
</module>
<module name="LocalFinalVariableName"/>
<!-- <module name="MagicNumber"/> invalid -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import io.github.mfvanek.pg.model.index.IndexWithBloat;
import io.github.mfvanek.pg.model.predicates.SkipBloatUnderThresholdPredicate;
import io.github.mfvanek.pg.model.predicates.SkipIndexesByNamePredicate;
import io.github.mfvanek.pg.model.predicates.SkipSmallIndexesPredicate;
import io.github.mfvanek.pg.model.predicates.SkipTablesByNamePredicate;
import io.github.mfvanek.pg.support.StatisticsAwareTestBase;
import org.assertj.core.api.Assertions;
Expand Down Expand Up @@ -72,6 +73,10 @@ void onDatabaseWithThem(final String schemaName) {
assertThat(check)
.executing(ctx, SkipBloatUnderThresholdPredicate.of(100_000L, 50.0))
.isEmpty();

assertThat(check)
.executing(ctx, SkipSmallIndexesPredicate.of(1_000_000L))
.isEmpty();
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,6 @@
package io.github.mfvanek.pg.common.health.logger;

import io.github.mfvanek.pg.checks.predicates.FilterDuplicatedIndexesByNamePredicate;
import io.github.mfvanek.pg.checks.predicates.FilterIndexesByBloatPredicate;
import io.github.mfvanek.pg.checks.predicates.FilterIndexesByNamePredicate;
import io.github.mfvanek.pg.checks.predicates.FilterIndexesBySizePredicate;
import io.github.mfvanek.pg.common.maintenance.DatabaseCheckOnCluster;
import io.github.mfvanek.pg.common.maintenance.DatabaseChecks;
import io.github.mfvanek.pg.common.maintenance.Diagnostic;
Expand All @@ -37,6 +34,7 @@
import io.github.mfvanek.pg.model.object.AnyObject;
import io.github.mfvanek.pg.model.predicates.SkipBloatUnderThresholdPredicate;
import io.github.mfvanek.pg.model.predicates.SkipIndexesByNamePredicate;
import io.github.mfvanek.pg.model.predicates.SkipSmallIndexesPredicate;
import io.github.mfvanek.pg.model.predicates.SkipSmallTablesPredicate;
import io.github.mfvanek.pg.model.predicates.SkipTablesByNamePredicate;
import io.github.mfvanek.pg.model.sequence.SequenceState;
Expand Down Expand Up @@ -144,8 +142,8 @@ private String logIntersectedIndexes(@Nonnull final Exclusions exclusions) {
@Nonnull
private String logUnusedIndexes(@Nonnull final Exclusions exclusions) {
return logCheckResult(databaseChecksHolder.get().getCheck(Diagnostic.UNUSED_INDEXES, UnusedIndex.class),
FilterIndexesBySizePredicate.of(exclusions.getIndexSizeThresholdInBytes())
.and(FilterIndexesByNamePredicate.of(exclusions.getUnusedIndexesExclusions())), SimpleLoggingKey.UNUSED_INDEXES);
SkipSmallIndexesPredicate.of(exclusions.getIndexSizeThresholdInBytes())
.and(SkipIndexesByNamePredicate.of(pgContextHolder.get(), exclusions.getUnusedIndexesExclusions())), SimpleLoggingKey.UNUSED_INDEXES);
}

@Nonnull
Expand All @@ -171,8 +169,8 @@ private String logIndexesWithNullValues(@Nonnull final Exclusions exclusions) {
@Nonnull
private String logIndexesBloat(@Nonnull final Exclusions exclusions) {
return logCheckResult(databaseChecksHolder.get().getCheck(Diagnostic.BLOATED_INDEXES, IndexWithBloat.class),
FilterIndexesByBloatPredicate.of(exclusions.getIndexBloatSizeThresholdInBytes(), exclusions.getIndexBloatPercentageThreshold())
.and(FilterIndexesBySizePredicate.of(exclusions.getIndexSizeThresholdInBytes())), SimpleLoggingKey.BLOATED_INDEXES);
SkipBloatUnderThresholdPredicate.of(exclusions.getIndexBloatSizeThresholdInBytes(), exclusions.getIndexBloatPercentageThreshold())
.and(SkipSmallIndexesPredicate.of(exclusions.getIndexSizeThresholdInBytes())), SimpleLoggingKey.BLOATED_INDEXES);
}

@Nonnull
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,14 @@ public class IndexWithColumns extends IndexWithSize {

private final List<Column> columns;

/**
* Constructs an {@code IndexWithColumns} with the specified table name, index name, size in bytes, and list of columns.
*
* @param tableName the name of the table associated with this index; must be non-blank.
* @param indexName the name of the index; must be non-blank.
* @param indexSizeInBytes the size of the index in bytes; must be zero or positive.
* @param columns the list of columns associated with the index; cannot be null.
*/
@SuppressWarnings("WeakerAccess")
protected IndexWithColumns(@Nonnull final String tableName,
@Nonnull final String indexName,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* Copyright (c) 2019-2024. Ivan Vakhrushev and others.
* https://github.com/mfvanek/pg-index-health
*
* This file is a part of "pg-index-health" - a Java library for
* analyzing and maintaining indexes health in PostgreSQL databases.
*
* Licensed under the Apache License 2.0
*/

package io.github.mfvanek.pg.model.predicates;

import io.github.mfvanek.pg.model.DbObject;
import io.github.mfvanek.pg.model.index.IndexSizeAware;

import java.util.function.Predicate;
import javax.annotation.Nonnull;
import javax.annotation.concurrent.Immutable;
import javax.annotation.concurrent.ThreadSafe;

/**
* A predicate that filters out small indexes based on a specified size threshold.
* This class extends {@link AbstractFilterBySize} and evaluates {@link IndexSizeAware}
* instances to determine if they meet or exceed the specified minimum index size.
*
* @author Ivan Vakhrushev
* @see IndexSizeAware
* @see DbObject
* @see AbstractFilterBySize
* @since 0.13.3
*/
@Immutable
@ThreadSafe
public final class SkipSmallIndexesPredicate extends AbstractFilterBySize {

private SkipSmallIndexesPredicate(final long thresholdInBytes) {
super(thresholdInBytes);
}

/**
* Evaluates whether the given {@link DbObject} should pass the filter based on its size.
* If the object is not an instance of {@link IndexSizeAware}, or if the threshold is zero,
* it automatically passes the filter. Otherwise, the object's size is compared to the threshold.
*
* @param dbObject the {@code DbObject} to be evaluated; must not be null.
* @return {@code true} if the table size is greater than or equal to the threshold, or if the object is not {@code IndexSizeAware}; {@code false} otherwise.
*/
@Override
public boolean test(@Nonnull final DbObject dbObject) {
if (thresholdInBytes == 0L) {
return true;
}
if (!(dbObject instanceof IndexSizeAware)) {
return true;
}
final IndexSizeAware indexSizeAware = (IndexSizeAware) dbObject;
return indexSizeAware.getIndexSizeInBytes() >= thresholdInBytes;
}

/**
* Creates a {@code SkipSmallIndexesPredicate} with the specified size threshold.
*
* @param thresholdInBytes the minimum index size in bytes required for an index to pass the filter; must be non-negative.
* @return a predicate that filters out indexes smaller than the specified size threshold.
*/
@Nonnull
public static Predicate<DbObject> of(final long thresholdInBytes) {
return new SkipSmallIndexesPredicate(thresholdInBytes);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,7 @@ public boolean test(@Nonnull final DbObject dbObject) {
/**
* Creates a {@code SkipSmallTablesPredicate} with the specified size threshold.
*
* @param thresholdInBytes the minimum table size in bytes required for a table to pass the filter;
* must be non-negative.
* @param thresholdInBytes the minimum table size in bytes required for a table to pass the filter; must be non-negative.
* @return a predicate that filters out tables smaller than the specified size threshold.
*/
@Nonnull
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* Copyright (c) 2019-2024. Ivan Vakhrushev and others.
* https://github.com/mfvanek/pg-index-health
*
* This file is a part of "pg-index-health" - a Java library for
* analyzing and maintaining indexes health in PostgreSQL databases.
*
* Licensed under the Apache License 2.0
*/

package io.github.mfvanek.pg.model.predicates;

import io.github.mfvanek.pg.model.index.IndexWithSize;
import io.github.mfvanek.pg.model.sequence.SequenceState;
import io.github.mfvanek.pg.model.table.Table;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

class SkipSmallIndexesPredicateTest {

@Test
void shouldThrowExceptionWhenInvalidDataPassed() {
assertThatThrownBy(() -> SkipSmallIndexesPredicate.of(-1L))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("thresholdInBytes cannot be less than zero");
}

@Test
void shouldNotCastObjectsWhenThresholdIsZero() {
final IndexWithSize mockIndex = Mockito.mock(IndexWithSize.class);
assertThat(SkipSmallIndexesPredicate.of(0L))
.accepts(mockIndex);
Mockito.verify(mockIndex, Mockito.never()).getIndexSizeInBytes();
}

@Test
void shouldWork() {
assertThat(SkipSmallIndexesPredicate.of(10L))
.accepts(Table.of("t", 0L))
.accepts(IndexWithSize.of("t", "i", 10L))
.accepts(IndexWithSize.of("t", "i", 11L))
.accepts(SequenceState.of("s1", "int", 80.0))
.rejects(IndexWithSize.of("t2", "i2", 9L));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@
*
* @author Ivan Vakhrushev
* @since 0.6.0
* @deprecated This class has been replaced by {@link io.github.mfvanek.pg.model.predicates.SkipSmallIndexesPredicate}
*/
@Deprecated(since = "0.13.3", forRemoval = true)
public class FilterIndexesBySizePredicate extends AbstractFilterBySize implements Predicate<IndexSizeAware> {

private FilterIndexesBySizePredicate(final long thresholdInBytes) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import io.github.mfvanek.pg.model.index.IndexWithBloat;
import io.github.mfvanek.pg.model.predicates.SkipBloatUnderThresholdPredicate;
import io.github.mfvanek.pg.model.predicates.SkipIndexesByNamePredicate;
import io.github.mfvanek.pg.model.predicates.SkipSmallIndexesPredicate;
import io.github.mfvanek.pg.model.predicates.SkipTablesByNamePredicate;
import io.github.mfvanek.pg.support.DatabasePopulator;
import io.github.mfvanek.pg.support.StatisticsAwareTestBase;
Expand Down Expand Up @@ -84,6 +85,10 @@ void onDatabaseWithThem(final String schemaName) {
assertThat(check)
.executing(ctx, SkipBloatUnderThresholdPredicate.of(100_000L, 50.0))
.isEmpty();

assertThat(check)
.executing(ctx, SkipSmallIndexesPredicate.of(1_000_000L))
.isEmpty();
});
}
}

0 comments on commit 3b65e9c

Please sign in to comment.