Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1vpUUI-009iHM-2D for pgsql-hackers@arkaria.postgresql.org; Mon, 09 Feb 2026 16:51:50 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1vpUUF-00BhND-2g for pgsql-hackers@arkaria.postgresql.org; Mon, 09 Feb 2026 16:51:47 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1vpUUF-00BhN4-1I for pgsql-hackers@lists.postgresql.org; Mon, 09 Feb 2026 16:51:47 +0000 Received: from mail-ej1-x634.google.com ([2a00:1450:4864:20::634]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1vpUUC-00000001IpP-3zh6 for pgsql-hackers@lists.postgresql.org; Mon, 09 Feb 2026 16:51:46 +0000 Received: by mail-ej1-x634.google.com with SMTP id a640c23a62f3a-b87677a8abeso706851066b.1 for ; Mon, 09 Feb 2026 08:51:44 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1770655902; cv=none; d=google.com; s=arc-20240605; b=lGs/Nfk/z8ahz8/xIAGuyEChL1qlcYdSdVnsZFFfrsp4QMGM3FCpVy+A/T0EKiujU/ gTiVyc0Sb59+gk5xRmQE1mlWKhJJSYO1UOmOQM/0Oj1CS5uZwDRdEUevwatwsNowG2bB IXG78EAkuF+J+59giWXr3LdOD7j3S6V8hQSbPsk7qpToStyjDpvC7rzmutjVO3kdJX5n lTM/LMbGGEW1Qmrrr/KoiQClR8qDNk6thX5DSMK/BZUO5cP3+6BpeNMfm6n8KzU8RLlz kTqBN8Yas/rziVSmwNHKp/kMDhsWJIxx6fGAT/sQyKpqgwxyDo1+C0VVDE5H8CrVkNYP SlfA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:dkim-signature; bh=/QRa7UQ5a50vyHXPxJituhBtMI3ID11jDu7FfU3OKn0=; fh=PugSoY9DT6VN5PjoWvU5zc7ZUEhz9JpqdIm7fftM0Oc=; b=eaNgH9sHRkBHkuzw6V8xoYZ1GU7lJA+KJuIcGa6sohn4457s0AFKPWT4m2+hjB2YNH IfhyJVMOrOkAamqmL6oIia96W4O7Tan4RZylyGkPM1CNnf1YLtUWS/C7YLuOFh34QKJe O56StzmC5qCKbzCYI8VF0KGktVyxDXuKtqjRkTsM6TUDP/6VIeERjlYOAgenopkensmp 0bC8Qx1vvWiZj6pSdQki6adRSh3Ou/tSEC0qtcLFMjGdjzqFxDVUAG1kSa9tmVcxBnTO L3TXYDKZkUv35riVWRL3+7wlNN9HTMgQSukWwpiBoOjl4b9pHX0kFAJxziaUYPpKaI+T pS2g==; darn=lists.postgresql.org ARC-Authentication-Results: i=1; mx.google.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1770655902; x=1771260702; darn=lists.postgresql.org; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=/QRa7UQ5a50vyHXPxJituhBtMI3ID11jDu7FfU3OKn0=; b=S+HJhrzT306ZX45G/wXx3gzxzkZQZovr15/+7fTM32oAVcpkf604VBWDGspzQ1EAjV BW2mChvstNrrAKK9uhgdqxgVvLjY1HuDRE/Qu3cUh4cioe/AtVjtzdSIOnvVYwlraRqv pxR6fch9y5y8oTP6s7iGo9EGZNfwjslPKfmdjJl8sjH5NDcynUx/raUt26F+qedvvw25 N1i9sp2q1Q1FnQEcKyUi/e92WaXqKHDL0cQSwwRP1iDhKXBI/7qqpYVVAa+ZgHu1HeFg 8ZHGYUslRAdOAq3yQPXlPJfzG1RnN95t2R3ZCrnM4yV6fE+T2sC8gm5/9QyWGaBXHW+r I7tg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1770655902; x=1771260702; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=/QRa7UQ5a50vyHXPxJituhBtMI3ID11jDu7FfU3OKn0=; b=o0awrN4zqRhIo9hV3WznOyvdWEm6N7fwn5mxG8ty3DQHsn3H23F/uC02zNvcJRVAXm zqH24XhM8ynlGmKViPQz3HwSJRd7GMo84+5pipRHTVUjOlf2fRq+ybPJFhAMmGOk07cK eDCuzZJG4h+bHSOcPKc8tIbVMuCFeq49KvaN5l2CXMFf591Xe4AlkC4x1nwoK6t0hedH ONwcnIwMFzjy98fMDTZYBy3aB5idwgnNyxnhIGHJDCueki5zKLoe8G5YYZoUFPsGoycj slcXC2c8uNSItn50juy3X2+PEt1mUZ6SsepSFrKIqIIIyoec4cskUrB9qkY15YB6ARPS PKQg== X-Forwarded-Encrypted: i=1; AJvYcCW9RSQ5hD5/34bFUMMR/VpdXMmC5liTI8JsTgkJ3PdyYJWc5VHZLtfEvLbZpous6vp+mCSkqiZZSe1w+hnH@lists.postgresql.org X-Gm-Message-State: AOJu0YyHlq/S2pZ3CsIxo8ZAft/1UoMbduhwmTclbpZEIRrR1hbHBJS/ 1t2anwfDmQLcR2YuOSRECX9eFrq0dnCvozsO6k2uWpEDn5topBTHyVOEpdYHc2LJIIYBw9K2ZVY akyGeM7e6lhBPymNXeiZy80/9JPppF6M= X-Gm-Gg: AZuq6aIMsaSNqYyS9pXdIH+MQcscq4bVLQhptIqAqvwxydvU04Q0ac8IuVppbjGNrgm ENOxo7huNDq80A+ZIgxjiDn+PnhJF/TuA78E05Mm17gu5YpvI/M9UpnVuzHDuJwTdiKtx+wY5y8 xaXJVWNbHs8tzbH4wFnFTmyX+YEV2Go56HINDQDCB++qmJpUk25VpN01/jAXZFqlX21BdzlWuLp 0mio1qzjjDju5tV3eBJIhMvglLmTfde6wfoKOfnN0d/0QtL9tD6uWeXLZV1F/3xFWPfG94= X-Received: by 2002:a17:907:6d01:b0:b87:10fd:b590 with SMTP id a640c23a62f3a-b8edf453b4dmr747882266b.60.1770655901790; Mon, 09 Feb 2026 08:51:41 -0800 (PST) MIME-Version: 1.0 References: In-Reply-To: From: Sami Imseih Date: Mon, 9 Feb 2026 10:51:30 -0600 X-Gm-Features: AZwV_QhkAFPwZ-AY_ZeMdKaq2M4fvaacQusnXx6lr265_kUGEV2DQ05frbvCwLM Message-ID: Subject: Re: [PATCH] Add last_executed timestamp to pg_stat_statements To: Christoph Berg Cc: Pavlo Golub , Bertrand Drouvot , "pgsql-hackers@lists.postgresql.org" Content-Type: text/plain; charset="UTF-8" List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk > > How about > > TimestampTz stmt_end = TimestampTzPlusMilliseconds( > > GetCurrentStatementStartTimestamp(), > > (int64) total_time > > ); > > We have total_time as an argument already! No kernel calls, sweet and easy! > > Cool idea! This calculation could be wrong for very common cases in extended query protocol, Here is a script to test with: ``` select pg_stat_statements_reset(); BEGIN; select now() as now, clock_timestamp() as clock_timestamp, pg_sleep($1) \bind 10 \g \! sleep 10 SELECT now() as now, clock_timestamp() as clock_timestamp, $1 \bind 1 \g END; select stats_last_updated, total_exec_time, substr(query, 1, 150) as query from pg_stat_statements; ```` With v3 applied, notice the output is calculating a stats_last_updated that is beyond the current time ``` pg_stat_statements_reset ------------------------------- 2026-02-09 16:13:35.188849+00 (1 row) BEGIN now | clock_timestamp | pg_sleep ------------------------------+-------------------------------+---------- 2026-02-09 16:13:35.18911+00 | 2026-02-09 16:13:35.189397+00 | (1 row) now | clock_timestamp | ?column? ------------------------------+-------------------------------+---------- 2026-02-09 16:13:35.18911+00 | 2026-02-09 16:13:55.193443+00 | 1 (1 row) COMMIT stats_last_updated | total_exec_time | query -------------------------------+-----------------+------------------------------------------------------------------------- 2026-02-09 16:13:55.19367+00 | 0.007401 | SELECT now() as now, clock_timestamp() as clock_timestamp, $1 2026-02-09 16:13:55.193664+00 | 0.00103 | END 2026-02-09 16:13:35.189111+00 | 0.00098 | BEGIN 2026-02-09 16:13:35.188584+00 | 0.090183 | select pg_stat_statements_reset() 2026-02-09 16:14:05.194134+00 | 10000.751122 | select now() as now, clock_timestamp() as clock_timestamp, pg_sleep($1) (5 rows) ``` This happens because in the case of extended query protocol, ExecutorEnd is called at the next query. This has been discussed in [1] [2]. So, for this to work, we will likely need to store the query start time in the queryDesc; actually queryDesc->totaltime, and set the query start time at ExecutorStart, during InstrAlloc. > > I think it's better because last_execution_start is already a known > > timestamp in pg_stat_activity.query_start and some tool that finds a > > long running query in pg_stat_activity, knowing the > > query_start they could then go look it up in pg_stat_statements. > > That only works if a) the query was not yet overwritten in > pg_stat_activity and b) neither in pg_stat_statements. Optimizing for > that use case seems pretty narrow. > > > What I'm really getting at is separating these fields will open up > > more use cases, IMO. Maybe this is a bad use case. But I felt separating these 2 fields will be more flexible. > Generally, I think pgss should have cumulative statistics, and less > about individual executions, so I'm not really sure what practical > problem "last start" and "last runtime" would solve. The > last_stats_update column we are talking about here is different in the > sense that it's not about an individual execution, but infrastructure > for retrieving the stats sensibly. Sure, generally, pg_stat_statements is for cumulative stats, but we also do have computed stats such as max/min/stddev, etc. But, it's not without precedent that we track timestamps of the last time some operation occurred. We do that in views that have a purpose of tracking cumulative data, because these timestamps are useful. See pg_stat_all_tables.last_seq_scan or last_autovacuum as an example. Maybe having the last runtime column is not that valuable if we can correctly calculate the last execution time. AlsoI will be a strong -1 calling this field "stats_last_updated" instead of "last_execution_time". [1] https://www.postgresql.org/message-id/3d07ee43-8855-42db-97e0-bad5db82d972@dalibo.com [2] https://www.postgresql.org/message-id/CAA5RZ0t2+GLnE_55L2cfCay+L8yPFpdPRVQo-JswUFgXy-EK5Q@mail.gmail.com -- Sami Imseih Amazon Web Services (AWS)