Re: Add usage counts to pg_buffercache
От | Russell Smith |
---|---|
Тема | Re: Add usage counts to pg_buffercache |
Дата | |
Msg-id | 460F1A07.9050709@pws.com.au обсуждение исходный текст |
Ответ на | Add usage counts to pg_buffercache (Greg Smith <gsmith@gregsmith.com>) |
Ответы |
Re: Add usage counts to pg_buffercache
|
Список | pgsql-patches |
Possibly minor detail; from buf_internals.h uint16 usage_count; /* usage counter for clock sweep code */ and you have a int16 to store that. Currently the max buffer count is 5. But is that a complete safe assumption? Maybe a compile time check that BM_MAX_USAGE_COUNT is < 16k would ensure that things don't go wrong? Regards Russell Smith Greg Smith wrote: > This patch adds the usage count statistic to the information available > in contrib/pgbuffercache. Earlier this month a discussion about my > first attempt to instrument the background writer had Tom asking for > details about the usage histogram I was seeing, and this patch proved > to be the easiest way I found to take a look at that. > > In situations where one is trying to optimize the background writer, > it's very hard to adjust how much to rely on the LRU writer versus the > one that writes everything unless you know whether your dirty buffers > are typically used heavily (like index blocks) or not (like new INSERT > data). Some statistics about the usage counts in your buffer cache > are extremely helpful in making that decision. > > I'll even pass along an ugly but fun query that utilizes this. The > following will give you a summary of your buffer cache broken into 32 > sections. Each line shows the average usage count of that section, as > a positive number if most buffers dirty and a negative one if most are > clean. If you refresh this frequently enough, you can actually watch > things like how checkpoints move through the buffer cache: > > SELECT current_timestamp, > -- Split into 32 bins of data > round(bufferid / (cast((select setting from pg_settings where > name='shared_buffers') as int) / (32 - 1.0))) > as section, round( > -- Average usage count, capped at 5 > case when avg(usagecount)>5 then 5 else avg(usagecount) end * > -- -1 when the majority are clean records, 1 when most are dirty > (case when sum(case when isdirty then 1 else -1 end)>0 then 1 else -1 > end)) as color_intensity > FROM pg_buffercache GROUP BY > round(bufferid / (cast((select setting from pg_settings where > name='shared_buffers') as int) / (32 - 1.0))); > > The 32 can be changed to anything, that's just what fits on my screen. > The main idea of the above is that if you dump all this to a file > regularly, it's possible to produce a graph of it showing how the > cache has changed over time by assigning a different color intensity > based on the usage count--at a massive cost in overhead, of course. > I'll be passing along all that code once I get it ready for other > people to use. > > -- > * Greg Smith gsmith@gregsmith.com http://www.gregsmith.com Baltimore, MD > ------------------------------------------------------------------------ > > Index: README.pg_buffercache > =================================================================== > RCS file: /projects/cvsroot/pgsql/contrib/pg_buffercache/README.pg_buffercache,v > retrieving revision 1.3 > diff -c -r1.3 README.pg_buffercache > *** README.pg_buffercache 26 Apr 2006 22:50:17 -0000 1.3 > --- README.pg_buffercache 1 Apr 2007 02:17:15 -0000 > *************** > *** 40,46 **** > reldatabase | pg_database.oid | Database for the relation. > relblocknumber | | Offset of the page in the relation. > isdirty | | Is the page dirty? > ! > > There is one row for each buffer in the shared cache. Unused buffers are > shown with all fields null except bufferid. > --- 40,46 ---- > reldatabase | pg_database.oid | Database for the relation. > relblocknumber | | Offset of the page in the relation. > isdirty | | Is the page dirty? > ! usagecount | | Page LRU count > > There is one row for each buffer in the shared cache. Unused buffers are > shown with all fields null except bufferid. > *************** > *** 60,79 **** > > regression=# \d pg_buffercache; > View "public.pg_buffercache" > ! Column | Type | Modifiers > ! ----------------+---------+----------- > ! bufferid | integer | > ! relfilenode | oid | > ! reltablespace | oid | > ! reldatabase | oid | > ! relblocknumber | bigint | > ! isdirty | boolean | > View definition: > SELECT p.bufferid, p.relfilenode, p.reltablespace, p.reldatabase, > ! p.relblocknumber, p.isdirty > FROM pg_buffercache_pages() p(bufferid integer, relfilenode oid, > reltablespace oid, reldatabase oid, relblocknumber bigint, > ! isdirty boolean); > > regression=# SELECT c.relname, count(*) AS buffers > FROM pg_class c INNER JOIN pg_buffercache b > --- 60,81 ---- > > regression=# \d pg_buffercache; > View "public.pg_buffercache" > ! Column | Type | Modifiers > ! ----------------+----------+----------- > ! bufferid | integer | > ! relfilenode | oid | > ! reltablespace | oid | > ! reldatabase | oid | > ! relblocknumber | bigint | > ! isdirty | boolean | > ! usagecount | smallint | > ! > View definition: > SELECT p.bufferid, p.relfilenode, p.reltablespace, p.reldatabase, > ! p.relblocknumber, p.isdirty, p.usagecount > FROM pg_buffercache_pages() p(bufferid integer, relfilenode oid, > reltablespace oid, reldatabase oid, relblocknumber bigint, > ! isdirty boolean, usagecount smallint); > > regression=# SELECT c.relname, count(*) AS buffers > FROM pg_class c INNER JOIN pg_buffercache b > Index: pg_buffercache.sql.in > =================================================================== > RCS file: /projects/cvsroot/pgsql/contrib/pg_buffercache/pg_buffercache.sql.in,v > retrieving revision 1.4 > diff -c -r1.4 pg_buffercache.sql.in > *** pg_buffercache.sql.in 26 Apr 2006 22:50:17 -0000 1.4 > --- pg_buffercache.sql.in 1 Apr 2007 02:17:15 -0000 > *************** > *** 12,18 **** > CREATE VIEW pg_buffercache AS > SELECT P.* FROM pg_buffercache_pages() AS P > (bufferid integer, relfilenode oid, reltablespace oid, reldatabase oid, > ! relblocknumber int8, isdirty bool); > > -- Don't want these to be available at public. > REVOKE ALL ON FUNCTION pg_buffercache_pages() FROM PUBLIC; > --- 12,18 ---- > CREATE VIEW pg_buffercache AS > SELECT P.* FROM pg_buffercache_pages() AS P > (bufferid integer, relfilenode oid, reltablespace oid, reldatabase oid, > ! relblocknumber int8, isdirty bool, usagecount int2); > > -- Don't want these to be available at public. > REVOKE ALL ON FUNCTION pg_buffercache_pages() FROM PUBLIC; > Index: pg_buffercache_pages.c > =================================================================== > RCS file: /projects/cvsroot/pgsql/contrib/pg_buffercache/pg_buffercache_pages.c,v > retrieving revision 1.11 > diff -c -r1.11 pg_buffercache_pages.c > *** pg_buffercache_pages.c 22 Oct 2006 17:49:21 -0000 1.11 > --- pg_buffercache_pages.c 1 Apr 2007 02:17:15 -0000 > *************** > *** 16,22 **** > #include "utils/relcache.h" > > > ! #define NUM_BUFFERCACHE_PAGES_ELEM 6 > > PG_MODULE_MAGIC; > > --- 16,22 ---- > #include "utils/relcache.h" > > > ! #define NUM_BUFFERCACHE_PAGES_ELEM 7 > > PG_MODULE_MAGIC; > > *************** > *** 35,40 **** > --- 35,41 ---- > BlockNumber blocknum; > bool isvalid; > bool isdirty; > + uint16 usagecount; > } BufferCachePagesRec; > > > *************** > *** 91,96 **** > --- 92,99 ---- > INT8OID, -1, 0); > TupleDescInitEntry(tupledesc, (AttrNumber) 6, "isdirty", > BOOLOID, -1, 0); > + TupleDescInitEntry(tupledesc, (AttrNumber) 7, "usage_count", > + INT2OID, -1, 0); > > fctx->tupdesc = BlessTupleDesc(tupledesc); > > *************** > *** 126,131 **** > --- 129,135 ---- > fctx->record[i].reltablespace = bufHdr->tag.rnode.spcNode; > fctx->record[i].reldatabase = bufHdr->tag.rnode.dbNode; > fctx->record[i].blocknum = bufHdr->tag.blockNum; > + fctx->record[i].usagecount = bufHdr->usage_count; > > if (bufHdr->flags & BM_DIRTY) > fctx->record[i].isdirty = true; > *************** > *** 172,177 **** > --- 176,182 ---- > nulls[3] = true; > nulls[4] = true; > nulls[5] = true; > + nulls[6] = true; > } > else > { > *************** > *** 185,190 **** > --- 190,197 ---- > nulls[4] = false; > values[5] = BoolGetDatum(fctx->record[i].isdirty); > nulls[5] = false; > + values[6] = Int16GetDatum(fctx->record[i].usagecount); > + nulls[6] = false; > } > > /* Build and return the tuple. */ > > ------------------------------------------------------------------------ > > > ---------------------------(end of broadcast)--------------------------- > TIP 4: Have you searched our list archives? > > http://archives.postgresql.org >
В списке pgsql-patches по дате отправления: