diff --git a/repository-ydb-v2/src/main/java/tech/ydb/yoj/repository/ydb/statement/FindInStatement.java b/repository-ydb-v2/src/main/java/tech/ydb/yoj/repository/ydb/statement/FindInStatement.java
index cefde5fa..e79c5ba4 100644
--- a/repository-ydb-v2/src/main/java/tech/ydb/yoj/repository/ydb/statement/FindInStatement.java
+++ b/repository-ydb-v2/src/main/java/tech/ydb/yoj/repository/ydb/statement/FindInStatement.java
@@ -127,75 +127,54 @@ public final class FindInStatement<IN, T extends Entity<T>, RESULT> extends Mult
      * @param orderBy      order by expression for result sorting, order fields must be present
      *                     in the {@code resultSchema}
      */
-    protected FindInStatement(
+    public static <ID extends Entity.Id<T>, T extends Entity<T>, RESULT> FindInStatement<Set<ID>, T, RESULT> from(
             EntitySchema<T> schema,
             Schema<RESULT> resultSchema,
-            Iterable<? extends Entity.Id<T>> ids,
+            Iterable<ID> ids,
             @Nullable FilterExpression<T> filter,
             @Nullable OrderExpression<T> orderBy,
             @Nullable Integer limit
     ) {
-        this(schema, resultSchema, ids, filter, orderBy, limit, schema.getName());
-    }
-
-    protected FindInStatement(
-            EntitySchema<T> schema,
-            Schema<RESULT> resultSchema,
-            Iterable<? extends Entity.Id<T>> ids,
-            @Nullable FilterExpression<T> filter,
-            @Nullable OrderExpression<T> orderBy,
-            @Nullable Integer limit,
-            String tableName
-    ) {
-        super(schema, resultSchema, tableName);
-
-        this.orderBy = orderBy;
-        this.limit = limit;
+        var keySchema = schema.getIdSchema();
+        var keyFields = collectKeyFieldsFromIds(schema.getIdSchema(), ids);
 
-        indexName = null;
-        keySchema = schema.getIdSchema();
-        keyFields = collectKeyFieldsFromIds(schema.getIdSchema(), ids);
-        predicate = (filter == null) ? null : new PredicateClause<>(schema, YqlListingQuery.toYqlPredicate(filter));
-
-        validateOrderByFields();
+        return new FindInStatement<>(schema, resultSchema, keySchema, keyFields, null, filter, orderBy, limit);
     }
 
-    /**
-     * Creates new {@code FindInStatement} instance with index usage and pagination.
-     */
-    protected <V> FindInStatement(
+    public static <K, T extends Entity<T>, RESULT> FindInStatement<Set<K>, T, RESULT> from(
             EntitySchema<T> schema,
             Schema<RESULT> resultSchema,
             String indexName,
-            Iterable<V> keys,
+            Iterable<K> keys,
             @Nullable FilterExpression<T> filter,
             @Nullable OrderExpression<T> orderBy,
             @Nullable Integer limit
     ) {
-        this(schema, resultSchema, indexName, keys, filter, orderBy, limit, schema.getName());
+        Schema<K> keySchema = getKeySchemaFromValues(keys);
+        Set<String> keyFields = collectKeyFieldsFromKeys(schema, indexName, keySchema, keys);
+
+        return new FindInStatement<>(schema, resultSchema, keySchema, keyFields, indexName, filter, orderBy, limit);
     }
 
-    protected <V> FindInStatement(
+    private <PARAMS> FindInStatement(
             EntitySchema<T> schema,
             Schema<RESULT> resultSchema,
-            String indexName,
-            Iterable<V> keys,
+            Schema<PARAMS> keySchema,
+            Set<String> keyFields,
+            @Nullable String indexName,
             @Nullable FilterExpression<T> filter,
             @Nullable OrderExpression<T> orderBy,
-            @Nullable Integer limit,
-            String tableName
+            @Nullable Integer limit
+
     ) {
-        super(schema, resultSchema, tableName);
+        super(schema, resultSchema);
 
         this.indexName = indexName;
         this.orderBy = orderBy;
         this.limit = limit;
-
-        Schema<V> schemaFromValues = getKeySchemaFromValues(keys);
-
-        keySchema = schemaFromValues;
-        keyFields = collectKeyFieldsFromKeys(schema, indexName, schemaFromValues, keys);
-        predicate = (filter == null) ? null : new PredicateClause<>(schema, YqlListingQuery.toYqlPredicate(filter));
+        this.keySchema = keySchema;
+        this.keyFields = keyFields;
+        this.predicate = (filter == null) ? null : new PredicateClause<>(schema, YqlListingQuery.toYqlPredicate(filter));
 
         validateOrderByFields();
     }
diff --git a/repository-ydb-v2/src/main/java/tech/ydb/yoj/repository/ydb/statement/YqlStatement.java b/repository-ydb-v2/src/main/java/tech/ydb/yoj/repository/ydb/statement/YqlStatement.java
index 51fa291f..db8e2f3f 100644
--- a/repository-ydb-v2/src/main/java/tech/ydb/yoj/repository/ydb/statement/YqlStatement.java
+++ b/repository-ydb-v2/src/main/java/tech/ydb/yoj/repository/ydb/statement/YqlStatement.java
@@ -4,8 +4,6 @@
 import com.google.protobuf.NullValue;
 import lombok.NonNull;
 import tech.ydb.proto.ValueProtos;
-import tech.ydb.yoj.databind.expression.FilterExpression;
-import tech.ydb.yoj.databind.expression.OrderExpression;
 import tech.ydb.yoj.databind.schema.ObjectSchema;
 import tech.ydb.yoj.databind.schema.Schema;
 import tech.ydb.yoj.repository.db.Entity;
@@ -92,60 +90,6 @@ public static <ENTITY extends Entity<ENTITY>, VIEW extends View, ID extends Enti
         return new FindRangeStatement<>(EntitySchema.of(type), ViewSchema.of(viewType), range);
     }
 
-    public static <PARAMS, ENTITY extends Entity<ENTITY>, ID extends Entity.Id<ENTITY>> Statement<PARAMS, ID> findIdsIn(
-            Class<ENTITY> type,
-            Iterable<ID> ids,
-            FilterExpression<ENTITY> filter,
-            OrderExpression<ENTITY> orderBy,
-            Integer limit
-    ) {
-        return new FindInStatement<>(EntitySchema.of(type), EntityIdSchema.ofEntity(type), ids, filter, orderBy, limit);
-    }
-
-    public static <PARAMS, ENTITY extends Entity<ENTITY>> Statement<PARAMS, ENTITY> findIn(
-            Class<ENTITY> type,
-            Iterable<? extends Entity.Id<ENTITY>> ids,
-            FilterExpression<ENTITY> filter,
-            OrderExpression<ENTITY> orderBy,
-            Integer limit
-    ) {
-        return new FindInStatement<>(EntitySchema.of(type), EntitySchema.of(type), ids, filter, orderBy, limit);
-    }
-
-    public static <PARAMS, ENTITY extends Entity<ENTITY>, VIEW extends View> Statement<PARAMS, VIEW> findIn(
-            Class<ENTITY> type,
-            Class<VIEW> viewType,
-            Iterable<? extends Entity.Id<ENTITY>> ids,
-            FilterExpression<ENTITY> filter,
-            OrderExpression<ENTITY> orderBy,
-            Integer limit
-    ) {
-        return new FindInStatement<>(EntitySchema.of(type), ViewSchema.of(viewType), ids, filter, orderBy, limit);
-    }
-
-    public static <PARAMS, ENTITY extends Entity<ENTITY>, K> Statement<PARAMS, ENTITY> findIn(
-            Class<ENTITY> type,
-            String indexName,
-            Iterable<K> keys,
-            FilterExpression<ENTITY> filter,
-            OrderExpression<ENTITY> orderBy,
-            Integer limit
-    ) {
-        return new FindInStatement<>(EntitySchema.of(type), EntitySchema.of(type), indexName, keys, filter, orderBy, limit);
-    }
-
-    public static <PARAMS, ENTITY extends Entity<ENTITY>, VIEW extends View, K> Statement<PARAMS, VIEW> findIn(
-            Class<ENTITY> type,
-            Class<VIEW> viewType,
-            String indexName,
-            Iterable<K> keys,
-            FilterExpression<ENTITY> filter,
-            OrderExpression<ENTITY> orderBy,
-            Integer limit
-    ) {
-        return new FindInStatement<>(EntitySchema.of(type), ViewSchema.of(viewType), indexName, keys, filter, orderBy, limit);
-    }
-
     public static <PARAMS, ENTITY extends Entity<ENTITY>> Statement<PARAMS, ENTITY> findAll(
             Class<ENTITY> type
     ) {
diff --git a/repository-ydb-v2/src/main/java/tech/ydb/yoj/repository/ydb/table/YdbTable.java b/repository-ydb-v2/src/main/java/tech/ydb/yoj/repository/ydb/table/YdbTable.java
index af6563cf..c577327a 100644
--- a/repository-ydb-v2/src/main/java/tech/ydb/yoj/repository/ydb/table/YdbTable.java
+++ b/repository-ydb-v2/src/main/java/tech/ydb/yoj/repository/ydb/table/YdbTable.java
@@ -24,6 +24,7 @@
 import tech.ydb.yoj.repository.ydb.bulk.BulkMapperImpl;
 import tech.ydb.yoj.repository.ydb.readtable.EntityIdKeyMapper;
 import tech.ydb.yoj.repository.ydb.readtable.ReadTableMapper;
+import tech.ydb.yoj.repository.ydb.statement.FindInStatement;
 import tech.ydb.yoj.repository.ydb.statement.FindStatement;
 import tech.ydb.yoj.repository.ydb.statement.FindYqlStatement;
 import tech.ydb.yoj.repository.ydb.statement.Statement;
@@ -328,7 +329,8 @@ public <ID extends Entity.Id<T>> List<T> findUncached(Set<ID> ids, @Nullable Fil
         if (ids.isEmpty()) {
             return List.of();
         }
-        return executor.execute(YqlStatement.findIn(type, ids, filter, orderBy, limit), ids);
+        var statement = FindInStatement.from(schema, schema, ids, filter, orderBy, limit);
+        return executor.execute(statement, ids);
     }
 
     @Override
@@ -336,7 +338,9 @@ public <V extends View, ID extends Id<T>> List<V> find(Class<V> viewType, Set<ID
         if (ids.isEmpty()) {
             return List.of();
         }
-        return executor.execute(YqlStatement.findIn(type, viewType, ids, filter, orderBy, limit), ids);
+        ViewSchema<V> viewSchema = ViewSchema.of(viewType);
+        var statement = FindInStatement.from(schema, viewSchema, ids, filter, orderBy, limit);
+        return executor.execute(statement, ids);
     }
 
     @Override
@@ -344,7 +348,8 @@ public <K> List<T> find(String indexName, Set<K> keys, @Nullable FilterExpressio
         if (keys.isEmpty()) {
             return List.of();
         }
-        return postLoad(executor.execute(YqlStatement.findIn(type, indexName, keys, filter, orderBy, limit), keys));
+        var statement = FindInStatement.from(schema, schema, indexName, keys, filter, orderBy, limit);
+        return postLoad(executor.execute(statement, keys));
     }
 
     @Override
@@ -352,7 +357,9 @@ public <V extends View, K> List<V> find(Class<V> viewType, String indexName, Set
         if (keys.isEmpty()) {
             return List.of();
         }
-        return executor.execute(YqlStatement.findIn(type, viewType, indexName, keys, filter, orderBy, limit), keys);
+        ViewSchema<V> viewSchema = ViewSchema.of(viewType);
+        var statement = FindInStatement.from(schema, viewSchema, indexName, keys, filter, orderBy, limit);
+        return executor.execute(statement, keys);
     }
 
     public static <T extends Entity<T>> List<YqlStatementPart<? extends YqlStatementPart<?>>> buildStatementParts(
@@ -416,7 +423,10 @@ public <ID extends Id<T>> List<ID> findIds(Set<ID> partialIds) {
         if (partialIds.isEmpty()) {
             return List.of();
         }
-        return executor.execute(YqlStatement.findIdsIn(type, partialIds, null, defaultOrder(type), null), partialIds);
+        OrderExpression<T> order = defaultOrder(type);
+        EntityIdSchema<ID> idSchema = EntityIdSchema.ofEntity(type);
+        var statement = FindInStatement.from(schema, idSchema, partialIds, null, order, null);
+        return executor.execute(statement, partialIds);
     }
 
     @Override
diff --git a/repository-ydb-v2/src/test/java/tech/ydb/yoj/repository/ydb/statement/FindInStatementIntegrationTest.java b/repository-ydb-v2/src/test/java/tech/ydb/yoj/repository/ydb/statement/FindInStatementIntegrationTest.java
index a1c1437f..40731ed2 100644
--- a/repository-ydb-v2/src/test/java/tech/ydb/yoj/repository/ydb/statement/FindInStatementIntegrationTest.java
+++ b/repository-ydb-v2/src/test/java/tech/ydb/yoj/repository/ydb/statement/FindInStatementIntegrationTest.java
@@ -49,28 +49,28 @@ public class FindInStatementIntegrationTest {
 
     @Test
     public void testGetQueryType() {
-        var statement = new FindInStatement<>(ENTITY_SCHEMA, ENTITY_SCHEMA, IDS, null, null, null);
+        var statement = FindInStatement.from(ENTITY_SCHEMA, ENTITY_SCHEMA, IDS, null, null, null);
 
         assertThat(statement.getQueryType()).isEqualTo(Statement.QueryType.SELECT);
     }
 
     @Test
     public void testToDebugString() {
-        var statement = new FindInStatement<>(ENTITY_SCHEMA, ENTITY_SCHEMA, IDS, null, null, null);
+        var statement = FindInStatement.from(ENTITY_SCHEMA, ENTITY_SCHEMA, IDS, null, null, null);
 
         assertThat(statement.toDebugString(IDS)).isNotBlank();
     }
 
     @Test
     public void testToDebugStringWithOrder() {
-        var statement = new FindInStatement<>(ENTITY_SCHEMA, ENTITY_SCHEMA, IDS, null, DEFAULT_ORDER, null);
+        var statement = FindInStatement.from(ENTITY_SCHEMA, ENTITY_SCHEMA, IDS, null, DEFAULT_ORDER, null);
 
         assertThat(statement.toDebugString(IDS)).isNotBlank();
     }
 
     @Test
     public void testEntityUnordered() {
-        var statement = new FindInStatement<>(ENTITY_SCHEMA, ENTITY_SCHEMA, IDS, null, null, null);
+        var statement = FindInStatement.from(ENTITY_SCHEMA, ENTITY_SCHEMA, IDS, null, null, null);
 
         String query = statement.getQuery("global/cloud/");
         String expected = """
@@ -86,7 +86,7 @@ FROM AS_TABLE($Input) AS k
 
     @Test
     public void testEntityDefaultOrder() {
-        var statement = new FindInStatement<>(ENTITY_SCHEMA, ENTITY_SCHEMA, IDS, null, DEFAULT_ORDER, null);
+        var statement = FindInStatement.from(ENTITY_SCHEMA, ENTITY_SCHEMA, IDS, null, DEFAULT_ORDER, null);
 
         String query = statement.getQuery("global/cloud/");
         String expected = """
@@ -103,7 +103,7 @@ FROM AS_TABLE($Input) AS k
 
     @Test
     public void testEntityCustomOrder() {
-        var statement = new FindInStatement<>(ENTITY_SCHEMA, ENTITY_SCHEMA, IDS, null,
+        var statement = FindInStatement.from(ENTITY_SCHEMA, ENTITY_SCHEMA, IDS, null,
                 newOrderBuilder(Foo.class)
                         .orderBy("id.key1").ascending()
                         .orderBy("value1").descending()
@@ -126,7 +126,7 @@ FROM AS_TABLE($Input) AS k
 
     @Test
     public void testViewUnordered() {
-        var statement = new FindInStatement<>(ENTITY_SCHEMA, VIEW_SCHEMA, IDS, null, null, null);
+        var statement = FindInStatement.from(ENTITY_SCHEMA, VIEW_SCHEMA, IDS, null, null, null);
 
         String query = statement.getQuery("global/cloud/");
         String expected = """
@@ -142,7 +142,7 @@ FROM AS_TABLE($Input) AS k
 
     @Test
     public void testViewDefaultOrder() {
-        var statement = new FindInStatement<>(ENTITY_SCHEMA, VIEW_SCHEMA, IDS, null, DEFAULT_ORDER, null);
+        var statement = FindInStatement.from(ENTITY_SCHEMA, VIEW_SCHEMA, IDS, null, DEFAULT_ORDER, null);
 
         String query = statement.getQuery("global/cloud/");
         String expected = """
@@ -159,7 +159,7 @@ FROM AS_TABLE($Input) AS k
 
     @Test
     public void testViewCustomOrder() {
-        var statement = new FindInStatement<>(ENTITY_SCHEMA, VIEW_SCHEMA, IDS, null,
+        var statement = FindInStatement.from(ENTITY_SCHEMA, VIEW_SCHEMA, IDS, null,
                 newOrderBuilder(Foo.class)
                         .orderBy("id.key1").ascending()
                         .orderBy("value1").descending()
@@ -182,7 +182,7 @@ FROM AS_TABLE($Input) AS k
 
     @Test(expected = IllegalArgumentException.class)
     public void testViewIncompatibleOrder() {
-        var statement = new FindInStatement<>(ENTITY_SCHEMA, VIEW_SCHEMA, IDS, null,
+        var statement = FindInStatement.from(ENTITY_SCHEMA, VIEW_SCHEMA, IDS, null,
                 newOrderBuilder(Foo.class)
                         .orderBy("value2").descending()
                         .build(),
@@ -198,7 +198,7 @@ public void testFilter() {
                 .where("value1").neq(42L)
                 .and("value2").in("v1", "v2")
                 .build();
-        var statement = new FindInStatement<>(ENTITY_SCHEMA, VIEW_SCHEMA, IDS, filter, DEFAULT_ORDER, null);
+        var statement = FindInStatement.from(ENTITY_SCHEMA, VIEW_SCHEMA, IDS, filter, DEFAULT_ORDER, null);
 
         String query = statement.getQuery("global/cloud/");
         String expected = """
@@ -225,7 +225,7 @@ public void testFilterOrderLimit() {
                 .where("value1").neq(42L)
                 .and("value2").in("v1", "v2")
                 .build();
-        var statement = new FindInStatement<>(ENTITY_SCHEMA, VIEW_SCHEMA, IDS, filter, DEFAULT_ORDER, 42);
+        var statement = FindInStatement.from(ENTITY_SCHEMA, VIEW_SCHEMA, IDS, filter, DEFAULT_ORDER, 42);
 
         String query = statement.getQuery("global/cloud/");
         String expected = """
@@ -249,7 +249,7 @@ FROM AS_TABLE($Input) AS k
 
     @Test
     public void testByIndex() {
-        var statement = new FindInStatement<>(
+        var statement = FindInStatement.from(
                 ENTITY_SCHEMA,
                 VIEW_SCHEMA,
                 INDEX_NAME,
@@ -272,7 +272,7 @@ FROM AS_TABLE($Input) AS k
     @Test
     public void testNotExistentIndex() {
         assertThatIllegalArgumentException()
-                .isThrownBy(() -> new FindInStatement<>(
+                .isThrownBy(() -> FindInStatement.from(
                         ENTITY_SCHEMA,
                         VIEW_SCHEMA,
                         NOT_EXISTENT_INDEX_NAME,
@@ -285,7 +285,7 @@ public void testNotExistentIndex() {
     @Test
     public void testByIndexInconsistentPrefixKeys() {
         assertThatIllegalArgumentException()
-                .isThrownBy(() -> new FindInStatement<>(
+                .isThrownBy(() -> FindInStatement.from(
                         ENTITY_SCHEMA,
                         VIEW_SCHEMA,
                         INDEX_NAME,
@@ -297,7 +297,7 @@ public void testByIndexInconsistentPrefixKeys() {
     @Test
     public void testByIndexNotPrefixKeys() {
         assertThatIllegalArgumentException()
-                .isThrownBy(() -> new FindInStatement<>(
+                .isThrownBy(() -> FindInStatement.from(
                         ENTITY_SCHEMA,
                         VIEW_SCHEMA,
                         INDEX_NAME,
@@ -309,7 +309,7 @@ public void testByIndexNotPrefixKeys() {
     @Test
     public void testByIndexNotIndexedKey() {
         assertThatIllegalArgumentException()
-                .isThrownBy(() -> new FindInStatement<>(
+                .isThrownBy(() -> FindInStatement.from(
                         ENTITY_SCHEMA,
                         VIEW_SCHEMA,
                         INDEX_NAME,
@@ -322,7 +322,7 @@ public void testByIndexNotIndexedKey() {
     @Test
     public void testByIndexInconsistentTypeKeys() {
         assertThatIllegalArgumentException()
-                .isThrownBy(() -> new FindInStatement<>(
+                .isThrownBy(() -> FindInStatement.from(
                         ENTITY_SCHEMA,
                         VIEW_SCHEMA,
                         INDEX_NAME,
@@ -334,7 +334,7 @@ public void testByIndexInconsistentTypeKeys() {
 
     @Test
     public void testToQueryParameters() {
-        var statement = new FindInStatement<>(ENTITY_SCHEMA, VIEW_SCHEMA, IDS, null, DEFAULT_ORDER, null);
+        var statement = FindInStatement.from(ENTITY_SCHEMA, VIEW_SCHEMA, IDS, null, DEFAULT_ORDER, null);
 
         Map<String, ValueProtos.TypedValue> queryParams = statement.toQueryParameters(IDS);
 
@@ -347,7 +347,7 @@ public void testToQueryParametersWithFilter() {
                 .where("value1").neq(42L)
                 .and("value2").in("v1", "v2")
                 .build();
-        var statement = new FindInStatement<>(ENTITY_SCHEMA, VIEW_SCHEMA, IDS, filter, DEFAULT_ORDER, null);
+        var statement = FindInStatement.from(ENTITY_SCHEMA, VIEW_SCHEMA, IDS, filter, DEFAULT_ORDER, null);
 
         Map<String, ValueProtos.TypedValue> queryParams = statement.toQueryParameters(IDS);
 
@@ -360,7 +360,7 @@ public void testEntityWithSimpleId() {
         var ids = List.of(Bar.Id.of("a"), Bar.Id.of("b"));
         var filter = newFilterBuilder(Bar.class).where("value").eq(100500L).build();
         var orderBy = orderById(Bar.class, OrderExpression.SortOrder.DESCENDING);
-        var statement = new FindInStatement<>(entitySchema, entitySchema, ids, filter, orderBy, 42);
+        var statement = FindInStatement.from(entitySchema, entitySchema, ids, filter, orderBy, 42);
 
         String query = statement.getQuery("global/cloud/");
         String expected = """