AMashenkov commented on a change in pull request #6529: IGNITE-11756: SQL: 
implement a table row count statistics for the local queries.
URL: https://github.com/apache/ignite/pull/6529#discussion_r285512757
 
 

 ##########
 File path: 
modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Table.java
 ##########
 @@ -1076,7 +1099,129 @@ public void removeIndex(Session session, Index h2Idx) {
 
     /** {@inheritDoc} */
     @Override public long getRowCountApproximation() {
-        return size.longValue();
+        if (!localQuery())
+            return 10_000; // Fallback to the previous behaviour.
+
+        refreshStatsIfNeeded();
+
+        return tblStats.primaryRowCount();
+    }
+
+    /**
+     * @return {@code True} if the current query is a local query.
+     */
+    private boolean localQuery() {
+        QueryContext qctx = contextRegistry().getThreadLocal();
+
+        assert qctx != null;
+
+        return qctx.local();
+    }
+
+    /**
+     * Refreshes table stats if they are outdated.
+     */
+    private void refreshStatsIfNeeded() {
+        TableStatistics stats = tblStats;
+
+        long statsTotalRowCnt = stats.totalRowCount();
+        long curTotalRowCnt = size.sum();
+
+        // Update stats if total table size changed significantly since the 
last stats update.
+        if (needRefreshStats(statsTotalRowCnt, curTotalRowCnt)) {
+            long primaryRowCnt = rowCountAllSegments(true);
+
+            tblStats = new TableStatistics(curTotalRowCnt, primaryRowCnt);
+        }
+    }
+
+    /**
+     * @param statsRowCnt Row count from statistics.
+     * @param actualRowCnt Actual row count.
+     * @return {@code True} if actual table size has changed more than the 
threshold since last stats update.
+     */
+    private static boolean needRefreshStats(long statsRowCnt, long 
actualRowCnt) {
+        double delta = U.safeAbs(statsRowCnt - actualRowCnt);
+
+        double relativeChange = delta / (statsRowCnt + 1); // Add 1 to avoid 
division by zero.
+
+        // Return true if actual table size has changed more than the 
threshold since last stats update.
+        return relativeChange > STATS_UPDATE_THRESHOLD;
+    }
+
+    /**
+     * Retrieves partitions rows count for all segments.
+     *
+     * @param primaryOnly If {@code true}, only primary rows will be counted.
+     * @return Primary rows count.
+     */
+    private long rowCountAllSegments(boolean primaryOnly) {
+        int segCnt = ((GridH2IndexBase)getUniqueIndex()).segmentsCount();
+
+        long size = 0;
+
+        for (int seg = 0; seg < segCnt; seg++)
+            size += rowCountForSegment(seg, primaryOnly);
+
+        return size;
+    }
+
+    /**
+     * Retrieves row count for the given segment.
+     *
+     * @param seg Segment.
+     * @param primaryOnly If {@code true}, only primary rows will be counted.
+     * @return Primary rows count.
+     */
+    private long rowCountForSegment(int seg, boolean primaryOnly) {
+        // Save previous context.
+        QueryContext prevQryCtx = contextRegistry().getThreadLocal();
+
+        contextRegistry().clearThreadLocal();
+
+        setRowCountContext(seg, primaryOnly);
+
+        try {
+            return getRowCount(null);
+        }
+        finally {
+            contextRegistry().clearThreadLocal();
+
+            // Restore the previous context.
+            contextRegistry().setThreadLocal(prevQryCtx);
+        }
+    }
+
+    /**
+     * @return Query context registry.
+     */
+    private QueryContextRegistry contextRegistry() {
+        return rowDescriptor().indexing().queryContextRegistry();
+    }
+
+    /**
+     * Sets temporary query context for retrieving partitions row count in the 
given segment.
+     *
+     * @param seg Segment.
+     * @param primaryOnly If {@code true}, only primary rows will be counted.
+     */
+    private void setRowCountContext(int seg, boolean primaryOnly) {
+        IgniteH2Indexing indexing = rowDescriptor().indexing();
+
+        AffinityTopologyVersion topVer = indexing.readyTopologyVersion();
+
+        boolean mvcc = 
indexing.kernalContext().cache().context().cacheContext(cacheId()).mvccEnabled();
 
 Review comment:
   Cache context is available via GridH2Talbe.cacheInfo.context() or 
desc.context().

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services

Reply via email to