Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 73c954d

Browse files
committed
tableam: sample scan.
This moves sample scan support to below tableam. It's not optional as there is, in contrast to e.g. bitmap heap scans, no alternative way to perform tablesample queries. If an AM can't deal with the block based API, it will have to throw an ERROR. The tableam callbacks for this are block based, but given the current TsmRoutine interface, that seems to be required. The new interface doesn't require TsmRoutines to perform visibility checks anymore - that requires the TsmRoutine to know details about the AM, which we want to avoid. To continue to allow taking the returned number of tuples account SampleScanState now has a donetuples field (which previously e.g. existed in SystemRowsSamplerData), which is only incremented after the visibility check succeeds. Author: Andres Freund Discussion: https://postgr.es/m/20180703070645.wchpu5muyto5n647@alap3.anarazel.de
1 parent 4bb5023 commit 73c954d

File tree

10 files changed

+382
-312
lines changed

10 files changed

+382
-312
lines changed

contrib/tsm_system_rows/tsm_system_rows.c

+15-71
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828

2929
#include "postgres.h"
3030

31-
#include "access/heapam.h"
3231
#include "access/relscan.h"
3332
#include "access/tsmapi.h"
3433
#include "catalog/pg_type.h"
@@ -46,7 +45,6 @@ typedef struct
4645
{
4746
uint32 seed; /* random seed */
4847
int64 ntuples; /* number of tuples to return */
49-
int64 donetuples; /* number of tuples already returned */
5048
OffsetNumber lt; /* last tuple returned from current block */
5149
BlockNumber doneblocks; /* number of already-scanned blocks */
5250
BlockNumber lb; /* last block visited */
@@ -67,11 +65,10 @@ static void system_rows_beginsamplescan(SampleScanState *node,
6765
Datum *params,
6866
int nparams,
6967
uint32 seed);
70-
static BlockNumber system_rows_nextsampleblock(SampleScanState *node);
68+
static BlockNumber system_rows_nextsampleblock(SampleScanState *node, BlockNumber nblocks);
7169
static OffsetNumber system_rows_nextsampletuple(SampleScanState *node,
7270
BlockNumber blockno,
7371
OffsetNumber maxoffset);
74-
static bool SampleOffsetVisible(OffsetNumber tupoffset, HeapScanDesc scan);
7572
static uint32 random_relative_prime(uint32 n, SamplerRandomState randstate);
7673

7774

@@ -187,7 +184,6 @@ system_rows_beginsamplescan(SampleScanState *node,
187184

188185
sampler->seed = seed;
189186
sampler->ntuples = ntuples;
190-
sampler->donetuples = 0;
191187
sampler->lt = InvalidOffsetNumber;
192188
sampler->doneblocks = 0;
193189
/* lb will be initialized during first NextSampleBlock call */
@@ -206,11 +202,9 @@ system_rows_beginsamplescan(SampleScanState *node,
206202
* Uses linear probing algorithm for picking next block.
207203
*/
208204
static BlockNumber
209-
system_rows_nextsampleblock(SampleScanState *node)
205+
system_rows_nextsampleblock(SampleScanState *node, BlockNumber nblocks)
210206
{
211207
SystemRowsSamplerData *sampler = (SystemRowsSamplerData *) node->tsm_state;
212-
TableScanDesc scan = node->ss.ss_currentScanDesc;
213-
HeapScanDesc hscan = (HeapScanDesc) scan;
214208

215209
/* First call within scan? */
216210
if (sampler->doneblocks == 0)
@@ -222,14 +216,14 @@ system_rows_nextsampleblock(SampleScanState *node)
222216
SamplerRandomState randstate;
223217

224218
/* If relation is empty, there's nothing to scan */
225-
if (hscan->rs_nblocks == 0)
219+
if (nblocks == 0)
226220
return InvalidBlockNumber;
227221

228222
/* We only need an RNG during this setup step */
229223
sampler_random_init_state(sampler->seed, randstate);
230224

231225
/* Compute nblocks/firstblock/step only once per query */
232-
sampler->nblocks = hscan->rs_nblocks;
226+
sampler->nblocks = nblocks;
233227

234228
/* Choose random starting block within the relation */
235229
/* (Actually this is the predecessor of the first block visited) */
@@ -246,7 +240,7 @@ system_rows_nextsampleblock(SampleScanState *node)
246240

247241
/* If we've read all blocks or returned all needed tuples, we're done */
248242
if (++sampler->doneblocks > sampler->nblocks ||
249-
sampler->donetuples >= sampler->ntuples)
243+
node->donetuples >= sampler->ntuples)
250244
return InvalidBlockNumber;
251245

252246
/*
@@ -259,7 +253,7 @@ system_rows_nextsampleblock(SampleScanState *node)
259253
{
260254
/* Advance lb, using uint64 arithmetic to forestall overflow */
261255
sampler->lb = ((uint64) sampler->lb + sampler->step) % sampler->nblocks;
262-
} while (sampler->lb >= hscan->rs_nblocks);
256+
} while (sampler->lb >= nblocks);
263257

264258
return sampler->lb;
265259
}
@@ -279,77 +273,27 @@ system_rows_nextsampletuple(SampleScanState *node,
279273
OffsetNumber maxoffset)
280274
{
281275
SystemRowsSamplerData *sampler = (SystemRowsSamplerData *) node->tsm_state;
282-
TableScanDesc scan = node->ss.ss_currentScanDesc;
283-
HeapScanDesc hscan = (HeapScanDesc) scan;
284276
OffsetNumber tupoffset = sampler->lt;
285277

286278
/* Quit if we've returned all needed tuples */
287-
if (sampler->donetuples >= sampler->ntuples)
279+
if (node->donetuples >= sampler->ntuples)
288280
return InvalidOffsetNumber;
289281

290-
/*
291-
* Because we should only count visible tuples as being returned, we need
292-
* to search for a visible tuple rather than just let the core code do it.
293-
*/
294-
295-
/* We rely on the data accumulated in pagemode access */
296-
Assert(scan->rs_pageatatime);
297-
for (;;)
298-
{
299-
/* Advance to next possible offset on page */
300-
if (tupoffset == InvalidOffsetNumber)
301-
tupoffset = FirstOffsetNumber;
302-
else
303-
tupoffset++;
304-
305-
/* Done? */
306-
if (tupoffset > maxoffset)
307-
{
308-
tupoffset = InvalidOffsetNumber;
309-
break;
310-
}
282+
/* Advance to next possible offset on page */
283+
if (tupoffset == InvalidOffsetNumber)
284+
tupoffset = FirstOffsetNumber;
285+
else
286+
tupoffset++;
311287

312-
/* Found a candidate? */
313-
if (SampleOffsetVisible(tupoffset, hscan))
314-
{
315-
sampler->donetuples++;
316-
break;
317-
}
318-
}
288+
/* Done? */
289+
if (tupoffset > maxoffset)
290+
tupoffset = InvalidOffsetNumber;
319291

320292
sampler->lt = tupoffset;
321293

322294
return tupoffset;
323295
}
324296

325-
/*
326-
* Check if tuple offset is visible
327-
*
328-
* In pageatatime mode, heapgetpage() already did visibility checks,
329-
* so just look at the info it left in rs_vistuples[].
330-
*/
331-
static bool
332-
SampleOffsetVisible(OffsetNumber tupoffset, HeapScanDesc scan)
333-
{
334-
int start = 0,
335-
end = scan->rs_ntuples - 1;
336-
337-
while (start <= end)
338-
{
339-
int mid = (start + end) / 2;
340-
OffsetNumber curoffset = scan->rs_vistuples[mid];
341-
342-
if (tupoffset == curoffset)
343-
return true;
344-
else if (tupoffset < curoffset)
345-
end = mid - 1;
346-
else
347-
start = mid + 1;
348-
}
349-
350-
return false;
351-
}
352-
353297
/*
354298
* Compute greatest common divisor of two uint32's.
355299
*/

contrib/tsm_system_time/tsm_system_time.c

+5-8
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626

2727
#include <math.h>
2828

29-
#include "access/heapam.h"
3029
#include "access/relscan.h"
3130
#include "access/tsmapi.h"
3231
#include "catalog/pg_type.h"
@@ -66,7 +65,7 @@ static void system_time_beginsamplescan(SampleScanState *node,
6665
Datum *params,
6766
int nparams,
6867
uint32 seed);
69-
static BlockNumber system_time_nextsampleblock(SampleScanState *node);
68+
static BlockNumber system_time_nextsampleblock(SampleScanState *node, BlockNumber nblocks);
7069
static OffsetNumber system_time_nextsampletuple(SampleScanState *node,
7170
BlockNumber blockno,
7271
OffsetNumber maxoffset);
@@ -213,11 +212,9 @@ system_time_beginsamplescan(SampleScanState *node,
213212
* Uses linear probing algorithm for picking next block.
214213
*/
215214
static BlockNumber
216-
system_time_nextsampleblock(SampleScanState *node)
215+
system_time_nextsampleblock(SampleScanState *node, BlockNumber nblocks)
217216
{
218217
SystemTimeSamplerData *sampler = (SystemTimeSamplerData *) node->tsm_state;
219-
TableScanDesc scan = node->ss.ss_currentScanDesc;
220-
HeapScanDesc hscan = (HeapScanDesc) scan;
221218
instr_time cur_time;
222219

223220
/* First call within scan? */
@@ -230,14 +227,14 @@ system_time_nextsampleblock(SampleScanState *node)
230227
SamplerRandomState randstate;
231228

232229
/* If relation is empty, there's nothing to scan */
233-
if (hscan->rs_nblocks == 0)
230+
if (nblocks == 0)
234231
return InvalidBlockNumber;
235232

236233
/* We only need an RNG during this setup step */
237234
sampler_random_init_state(sampler->seed, randstate);
238235

239236
/* Compute nblocks/firstblock/step only once per query */
240-
sampler->nblocks = hscan->rs_nblocks;
237+
sampler->nblocks = nblocks;
241238

242239
/* Choose random starting block within the relation */
243240
/* (Actually this is the predecessor of the first block visited) */
@@ -273,7 +270,7 @@ system_time_nextsampleblock(SampleScanState *node)
273270
{
274271
/* Advance lb, using uint64 arithmetic to forestall overflow */
275272
sampler->lb = ((uint64) sampler->lb + sampler->step) % sampler->nblocks;
276-
} while (sampler->lb >= hscan->rs_nblocks);
273+
} while (sampler->lb >= nblocks);
277274

278275
return sampler->lb;
279276
}

doc/src/sgml/tablesample-method.sgml

+4-5
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ BeginSampleScan (SampleScanState *node,
227227
<para>
228228
<programlisting>
229229
BlockNumber
230-
NextSampleBlock (SampleScanState *node);
230+
NextSampleBlock (SampleScanState *node, BlockNumber nblocks);
231231
</programlisting>
232232

233233
Returns the block number of the next page to be scanned, or
@@ -262,10 +262,9 @@ NextSampleTuple (SampleScanState *node,
262262
numbers in the range <literal>1 .. maxoffset</literal> actually contain valid
263263
tuples. This is not normally a problem since the core code ignores
264264
requests to sample missing or invisible tuples; that should not result in
265-
any bias in the sample. However, if necessary, the function can
266-
examine <literal>node-&gt;ss.ss_currentScanDesc-&gt;rs_vistuples[]</literal>
267-
to identify which tuples are valid and visible. (This
268-
requires <literal>node-&gt;use_pagemode</literal> to be <literal>true</literal>.)
265+
any bias in the sample. However, if necessary, the function can use
266+
<literal>node-&gt;donetuples</literal> to examine how many of the tuples
267+
it returned were vlaid and visible.
269268
</para>
270269
</note>
271270

0 commit comments

Comments
 (0)