Source code for relstorage.adapters.postgresql.stats
################################################################################ Copyright (c) 2009 Zope Foundation and Contributors.# All Rights Reserved.## This software is subject to the provisions of the Zope Public License,# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS# FOR A PARTICULAR PURPOSE.###############################################################################"""Stats implementations"""from__future__importabsolute_importfrom..statsimportAbstractStatsfrom.._utilimportquery_property
[docs]classPostgreSQLStats(AbstractStats):# Getting the COUNT(*) of tables can be very expensive# due to the need to examine rows to check their MVCC visibility.# This method only promises to get the *approximate* size,# so we use the tables the optimizer uses to get stats.# With the autovacuum daemon running, this shouldn't get *too* far# out of date.# (https://www.postgresql.org/docs/11/monitoring-stats.html#PG-STAT-ALL-TABLES-VIEW)_get_object_count_queries=("SELECT reltuples::bigint FROM pg_class WHERE relname = 'current_object'","SELECT reltuples::bigint FROM pg_class WHERE relname = 'object_state'")_get_object_count_query=query_property('_get_object_count')_update_object_count_queries=(# Only on PG11 can you list more than one table.'ANALYZE current_object','ANALYZE object_state')_update_object_count_query=query_property('_update_object_count')
[docs]defget_object_count(self):"""Returns the approximate number of objects in the database"""conn,cursor=self.connmanager.open_for_load()try:cursor.execute(self._get_object_count_query)# If the tables haven't been analyzed, this could be None?# Or, somehow negative? 0 seems most likely, but just in case,# we check both.# Seen on GithubActions macos/py3.7/psycopg2, sept 2022.# Not seen before.returnmax(cursor.fetchone()[0]or0,0)finally:self.connmanager.close(conn,cursor)
[docs]defget_db_size(self):"""Returns the approximate size of the database in bytes"""defget_size(_conn,cursor):cursor.execute("SELECT pg_database_size(current_database())")returncursor.fetchone()[0]returnself.connmanager.open_and_call(get_size)
[docs]deflarge_database_change(self):defanalyze(_conn,cursor):# VACUUM cannot be run inside a transaction block;# ANALYZE can be. Both update pg_class.reltuples.# VACUUM needs a read table lock, meaning it can be blocked by writes# and vice-versa; ANALYZE doesn't appear to need locks.cursor.execute(self._update_object_count_query)# Depending on the number of pages this touched, the estimate# can be better or worse.self.connmanager.open_and_call(analyze)