Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit9563d5b

Browse files
committed
Add regression test case exercising the sorting path for hash index build.
We've broken this code path at least twice in the past, so it's prudentto have a test case that covers it. To allow exercising the code pathwithout creating a very large (and slow to run) test case, redefine thesort threshold to be bounded by maintenance_work_mem as well as the numberof available buffers. While at it, fix an ancient oversight that whenbuilding a temp index, the number of available buffers is not NBuffers butNLocBuffer. Also, if assertions are enabled, apply a direct test that thesort actually does return the tuples in the expected order.Peter GeogheganPatch: <CAM3SWZTBAo4hjbBd780+MrOKiKp_TMo1N3A0Rw9_im8gbD7fQA@mail.gmail.com>
1 parent2781489 commit9563d5b

File tree

4 files changed

+51
-6
lines changed

4 files changed

+51
-6
lines changed

‎src/backend/access/hash/hash.c

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include"access/relscan.h"
2323
#include"catalog/index.h"
2424
#include"commands/vacuum.h"
25+
#include"miscadmin.h"
2526
#include"optimizer/plancat.h"
2627
#include"utils/index_selfuncs.h"
2728
#include"utils/rel.h"
@@ -97,6 +98,7 @@ hashbuild(Relation heap, Relation index, IndexInfo *indexInfo)
9798
doublereltuples;
9899
doubleallvisfrac;
99100
uint32num_buckets;
101+
longsort_threshold;
100102
HashBuildStatebuildstate;
101103

102104
/*
@@ -120,12 +122,24 @@ hashbuild(Relation heap, Relation index, IndexInfo *indexInfo)
120122
* then we'll thrash horribly. To prevent that scenario, we can sort the
121123
* tuples by (expected) bucket number. However, such a sort is useless
122124
* overhead when the index does fit in RAM. We choose to sort if the
123-
* initial index size exceeds NBuffers.
125+
* initial index size exceeds maintenance_work_mem, or the number of
126+
* buffers usable for the index, whichever is less. (Limiting by the
127+
* number of buffers should reduce thrashing between PG buffers and kernel
128+
* buffers, which seems useful even if no physical I/O results. Limiting
129+
* by maintenance_work_mem is useful to allow easy testing of the sort
130+
* code path, and may be useful to DBAs as an additional control knob.)
124131
*
125132
* NOTE: this test will need adjustment if a bucket is ever different from
126-
* one page.
133+
* one page. Also, "initial index size" accounting does not include the
134+
* metapage, nor the first bitmap page.
127135
*/
128-
if (num_buckets >= (uint32)NBuffers)
136+
sort_threshold= (maintenance_work_mem*1024L) /BLCKSZ;
137+
if (index->rd_rel->relpersistence!=RELPERSISTENCE_TEMP)
138+
sort_threshold=Min(sort_threshold,NBuffers);
139+
else
140+
sort_threshold=Min(sort_threshold,NLocBuffer);
141+
142+
if (num_buckets >= (uint32)sort_threshold)
129143
buildstate.spool=_h_spoolinit(heap,index,num_buckets);
130144
else
131145
buildstate.spool=NULL;

‎src/backend/access/hash/hashsort.c

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ struct HSpool
3737
{
3838
Tuplesortstate*sortstate;/* state data for tuplesort.c */
3939
Relationindex;
40+
uint32hash_mask;/* bitmask for hash codes */
4041
};
4142

4243

@@ -47,7 +48,6 @@ HSpool *
4748
_h_spoolinit(Relationheap,Relationindex,uint32num_buckets)
4849
{
4950
HSpool*hspool= (HSpool*)palloc0(sizeof(HSpool));
50-
uint32hash_mask;
5151

5252
hspool->index=index;
5353

@@ -60,7 +60,7 @@ _h_spoolinit(Relation heap, Relation index, uint32 num_buckets)
6060
* we could just compute num_buckets - 1. We prefer not to assume that
6161
* here, though.
6262
*/
63-
hash_mask= (((uint32)1) <<_hash_log2(num_buckets))-1;
63+
hspool->hash_mask= (((uint32)1) <<_hash_log2(num_buckets))-1;
6464

6565
/*
6666
* We size the sort area as maintenance_work_mem rather than work_mem to
@@ -69,7 +69,7 @@ _h_spoolinit(Relation heap, Relation index, uint32 num_buckets)
6969
*/
7070
hspool->sortstate=tuplesort_begin_index_hash(heap,
7171
index,
72-
hash_mask,
72+
hspool->hash_mask,
7373
maintenance_work_mem,
7474
false);
7575

@@ -105,12 +105,29 @@ _h_indexbuild(HSpool *hspool)
105105
{
106106
IndexTupleitup;
107107
boolshould_free;
108+
#ifdefUSE_ASSERT_CHECKING
109+
uint32hashkey=0;
110+
#endif
108111

109112
tuplesort_performsort(hspool->sortstate);
110113

111114
while ((itup=tuplesort_getindextuple(hspool->sortstate,
112115
true,&should_free))!=NULL)
113116
{
117+
/*
118+
* Technically, it isn't critical that hash keys be found in sorted
119+
* order, since this sorting is only used to increase locality of
120+
* access as a performance optimization. It still seems like a good
121+
* idea to test tuplesort.c's handling of hash index tuple sorts
122+
* through an assertion, though.
123+
*/
124+
#ifdefUSE_ASSERT_CHECKING
125+
uint32lasthashkey=hashkey;
126+
127+
hashkey=_hash_get_indextuple_hashkey(itup)&hspool->hash_mask;
128+
Assert(hashkey >=lasthashkey);
129+
#endif
130+
114131
_hash_doinsert(hspool->index,itup);
115132
if (should_free)
116133
pfree(itup);

‎src/test/regress/expected/create_index.out

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2346,6 +2346,13 @@ CREATE UNLOGGED TABLE unlogged_hash_table (id int4);
23462346
CREATE INDEX unlogged_hash_index ON unlogged_hash_table USING hash (id int4_ops);
23472347
DROP TABLE unlogged_hash_table;
23482348
-- CREATE INDEX hash_ovfl_index ON hash_ovfl_heap USING hash (x int4_ops);
2349+
-- Test hash index build tuplesorting. Force hash tuplesort using low
2350+
-- maintenance_work_mem setting and fillfactor:
2351+
SET maintenance_work_mem = '1MB';
2352+
CREATE INDEX hash_tuplesort_idx ON tenk1 USING hash (stringu1 name_ops) WITH (fillfactor = 10);
2353+
WARNING: hash indexes are not WAL-logged and their use is discouraged
2354+
DROP INDEX hash_tuplesort_idx;
2355+
RESET maintenance_work_mem;
23492356
--
23502357
-- Test functional index
23512358
--

‎src/test/regress/sql/create_index.sql

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -690,6 +690,13 @@ DROP TABLE unlogged_hash_table;
690690

691691
-- CREATE INDEX hash_ovfl_index ON hash_ovfl_heap USING hash (x int4_ops);
692692

693+
-- Test hash index build tuplesorting. Force hash tuplesort using low
694+
-- maintenance_work_mem setting and fillfactor:
695+
SET maintenance_work_mem='1MB';
696+
CREATEINDEXhash_tuplesort_idxON tenk1 USING hash (stringu1 name_ops) WITH (fillfactor=10);
697+
DROPINDEX hash_tuplesort_idx;
698+
RESET maintenance_work_mem;
699+
693700

694701
--
695702
-- Test functional index

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp