Over 1000 gaps triggers Oracle "1000 elements in list" limitation
See original GitHub issueThe number of gaps in the events processed by a tracking event processor occasionally exceeds 1000, which triggers the Oracle limitation of maximum number of elements in an IN-clause. We would like a work-around in Axon Framework to handle this situation by splitting the IN-clause in as many IN-clauses as needed, concatenated by OR’s.
We think the following code in org.axonframework.eventsourcing.eventstore.jdbc.JdbcEventStorageEngine
(version 4.0.3) would do this:
protected PreparedStatement readEventDataAxon(Connection connection, TrackingToken lastToken,
int batchSize) throws SQLException {
isTrue(lastToken == null || lastToken instanceof GapAwareTrackingToken,
() -> format("Token [%s] is of the wrong type", lastToken));
GapAwareTrackingToken previousToken = (GapAwareTrackingToken) lastToken;
String sql = "SELECT " + trackedEventFields() + " FROM " + schema.domainEventTable() +
" WHERE (" + schema.globalIndexColumn() + " > ? AND " + schema.globalIndexColumn() + " <= ?) ";
List<Long> gaps;
if (previousToken != null) {
gaps = new ArrayList<>(previousToken.getGaps());
if (!gaps.isEmpty()) {
// sql += " OR " + schema.globalIndexColumn() + " IN (" +
// String.join(",", Collections.nCopies(gaps.size(), "?")) + ") ";
final AtomicInteger counter = new AtomicInteger(0);
sql += " OR " + Collections
.nCopies(gaps.size(), "?")
.stream()
.collect(Collectors.groupingBy(it -> counter.getAndIncrement() / 1000))
.values()
.stream()
.map(placeholders -> placeholders.stream().collect(Collectors.joining(", ", schema.globalIndexColumn() + " IN (", ")")))
.collect(Collectors.joining(" OR "));
}
} else {
gaps = Collections.emptyList();
}
sql += "ORDER BY " + schema.globalIndexColumn() + " ASC";
PreparedStatement preparedStatement = connection.prepareStatement(sql);
long globalIndex = previousToken == null ? -1 : previousToken.getIndex();
preparedStatement.setLong(1, globalIndex);
preparedStatement.setLong(2, globalIndex + batchSize);
for (int i = 0; i < gaps.size(); i++) {
preparedStatement.setLong(i + 3, gaps.get(i));
}
return preparedStatement;
}
The same solution would be applicable to version 3.x.
Issue Analytics
- State:
- Created 5 years ago
- Comments:6 (4 by maintainers)
Top Results From Across the Web
Limit and conversion very long IN list : WHERE x IN - Ask TOM
Oracle has the 1000 elements limit for IN lists for whatever reason (not very clear to me), but it does not enforce it...
Read more >Problem with BULK COLLECT with million rows - Ask TOM
Use the LIMIT clause, bulk collect say 100 to 1000 rows -- process them, bulk insert them, get the next 100/1000 rows. You...
Read more >varying elements in IN list - Ask TOM
varying elements in IN list I am using Oracle Report Builder 3.0.5.8.0 . While using bind refernce i have created a dynamic list...
Read more >Remove 1000 limit on IN clause - Oracle Communities
In Oracle we can only put up to 1000 values into an IN clause. I would like to see this restriction dropped.
Read more >ORA-01795: maximum number of expressions in a list is 1000 ...
when ever values specified for 'IN' operator in select statement exceeds 1000 then I am getting this error. How to over come this...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
Thanks @smcvb, that’s exactly what we are doing. At the same time we wanted to be good open source community citizens and offer our solution to whoever would benefit from it.
This issue has been the subject of discussions several times, here. On one hand, we do see there are some optimizations that could be done in the framework. However, we feel that the root cause is in the occurrence of the high number of gaps, in the first place. Configuring the database to work with dedicated sequences for the Domain Event Entry table is a solution that targets the root cause. Ultimately, there is always the possibility to tweak the exact SQL statements performed by the Storage Engine to resolve database-specific issues that may arise.
Since there are enough alternatives, we have decided not to build anything specific into Axon to resolve this issue.