Hi hackers,
While I was reviewing some code in another patch, I stumbled upon a possible optimization in the btree index code in nbtsearch.c for queries using 'LIMIT 1'. I have written a small patch that implements this optimization, but I'd like some feedback on the design of the patch, whether it is correct at all to use this optimization, and whether the performance tradeoffs are deemed worth it by the community. Basically, an example of the case I'd like to optimize is the following. Given a table 'tbl' with an index on columns (k,ts DESC): SELECT* FROM tbl WHERE k=:val AND ts<=:timestamp ORDER BY k, ts DESC LIMIT 1; And, even more importantly, when this query gets called in an inner loop like: SELECT* FROM generate_series(:start_ts, :end_ts, :interval) ts -- perhaps thousands of iterations, could also be a loop over values of 'k' rather than timestamps. this is just an example CROSS JOIN LATERAL ( SELECT* FROM tbl WHERE k=:val AND ts<=:timestamp ORDER BY k, ts DESC LIMIT 1; ) _; With time-series data, this case often arises as you have a certain natural key for which you store updates as they occur. Getting the state of k at a specific time then boils down to the given query there, which is almost always the fastest way to get this information, since the index scan with LIMIT 1 is very fast already. However, there seems to be a possibility to make this even faster (up to nearly 3x faster in test cases that use this nested loop of index scans) Every time the index scan is done, all tuples from the leaf page are read in nbtsearch.c:_bt_readpage. The idea of this patch is to make an exception for this *only* the first time amgettuple gets called. This calls _bt_first in nbtsearch.c, which will, if there are scankeys, descend the tree to a leaf page and read just the first (or possibly two) tuples. It won't touch the rest of the page yet. If indeed just one tuple was required, there won't be a call to _bt_next and we're done. If we do need more than one tuple, _bt_next will resume reading tuples from the index page at the point where we left off. There are a few caveats: - Possible performance decrease for queries that need a small number of tuples (but more than one), because they now need to lock the same page twice. This can happen in several cases, for example: LIMIT 3; LIMIT 1 but the first tuple returned does not match other scan conditions; LIMIT 1 but the tuple returned is not visible; no LIMIT at all but there are just only a few matching rows. - We need to take into account page splits, insertions and vacuums while we do not have the read-lock in between _bt_first and the first call to _bt_next. This made my patch quite a bit more complicated than my initial implementation. I did performance tests for some best case and worst case test scenarios. TPS results were stable and reproducible in re-runs on my, otherwise idle, server. Attached are the full results and how to reproduce. I picked test cases that show best performance as well as worst performance compared to master. Summary: the greatest performance improvement can be seen for the cases with the subquery in a nested loop. In a nested loop of 100 times, the performance is roughly two times better, for 10000 times the performance is roughly three times better. For most test cases that don't use LIMIT 1, I couldn't find a noticeable difference, except for the nested loop with a LIMIT 3 (or similarly, a nested loop without any LIMIT-clause that returns just three tuples). This is also theoretically the worst-case test case, because it has to lock the page again and then read it, just for one tuple. In this case, I saw TPS decrease by 2-3% in a few cases (details in the attached file), due to it having to lock/unlock the same page in both _bt_first and _bt_next. A few concrete questions to the community: - Does the community also see this as a useful optimization? - Is the way it is currently implemented safe? I struggled quite a bit to get everything working with respect to page splits and insertions. In particular, I don't know why in my patch, _bt_find_offset_for_tid needs to consider searching for items with an offset *before* the passed offset. As far as my understanding goes, this could only happen when the index gets vacuumed in the mean-time. However, we hold a pin on the buffer the whole time (we even assert this), so vacuum should not have been possible. Still, this code gets triggered sometimes, so it seems to be necessary. Perhaps someone in the community who's more of an expert on this can shed some light on it. - What are considered acceptable performance tradeoffs in this case? Is a performance degradation in any part generally not acceptable at all? I'd also welcome any feedback on the process - this is my first patch and while I tried to follow the guidelines, I may have missed something along the way. Attachments: - out_limit.txt: pgbench results for patched branch - out_master.txt pgbench results for master branch (can be diffed with out_limit.txt to efficiently see the difference) - init_test.sql: creates a simple table for the test cases and fills it with data - test_fwd.sql: the nested loop example, parameters :nlimit and :nitems to specify how many rows per inner loop to limit to and how many iterations of the loop need to be done. we're returning a sum() over a column to make sure transferring result data over the socket is not the bottleneck - this is to show the worst-case behavior of this patch. When selecting the full row instead of the sum, the performance difference is negligible for the 'bad' cases, while still providing great (up to 2.5x) improvements for the 'good' cases. This can be tested by changing the sum() to select a column per row instead. - test_fwd_eq.sql: nested loop with simple unique equality select - test_fwd_single.sql: single query with LIMIT without nested loop -Floris
0001-Optimize-single-tuple-fetch-from-nbtree-index-v01.patch
Description: 0001-Optimize-single-tuple-fetch-from-nbtree-index-v01.patch
init_test.sql
Description: init_test.sql
+++++ dirname ./test_limit.sh ++++ cd . ++++ pwd +++ DIR=/home/florisvannee/workspace/pg_dev/limit +++ T=20 +++ /home/florisvannee/workspace/pg_dev/start.sh ++++ [[ 0 -eq 2 ]] ++++ [[ 0 -eq 1 ]] ++++ bdir=/home/florisvannee/workspace/postgres ++++ cd /home/florisvannee/workspace/postgres +++++ git rev-parse --abbrev-ref HEAD ++++ totaldir=limit-release ++++ /home/florisvannee/install/limit-release/bin/pg_ctl -D/home/florisvannee/pgdata/limit-release -l /home/florisvannee/pgdata/limit-release/logfile -t 5 stop pg_ctl: could not send stop signal (PID: 28145): No such process ++++ pkill -9 postgres ++++ /home/florisvannee/install/limit-release/bin/pg_ctl -D/home/florisvannee/pgdata/limit-release -l /home/florisvannee/pgdata/limit-release/logfile start pg_ctl: another server might be running; trying to start server anyway waiting for server to start.... done server started +++ pgbench -n -f /home/florisvannee/workspace/pg_dev/limit/test_fwd_eq.sql -T 20 postgres -Dnitems=1 transaction type: /home/florisvannee/workspace/pg_dev/limit/test_fwd_eq.sql scaling factor: 1 query mode: simple number of clients: 1 number of threads: 1 duration: 20 s number of transactions actually processed: 156764 latency average = 0.128 ms tps = 7838.184195 (including connections establishing) tps = 7839.331599 (excluding connections establishing) +++ pgbench -n -f /home/florisvannee/workspace/pg_dev/limit/test_fwd_eq.sql -T 20 postgres -Dnitems=10 transaction type: /home/florisvannee/workspace/pg_dev/limit/test_fwd_eq.sql scaling factor: 1 query mode: simple number of clients: 1 number of threads: 1 duration: 20 s number of transactions actually processed: 131079 latency average = 0.153 ms tps = 6553.920794 (including connections establishing) tps = 6554.874046 (excluding connections establishing) +++ pgbench -n -f /home/florisvannee/workspace/pg_dev/limit/test_fwd_eq.sql -T 20 postgres -Dnitems=100 transaction type: /home/florisvannee/workspace/pg_dev/limit/test_fwd_eq.sql scaling factor: 1 query mode: simple number of clients: 1 number of threads: 1 duration: 20 s number of transactions actually processed: 50692 latency average = 0.395 ms tps = 2534.595231 (including connections establishing) tps = 2534.967502 (excluding connections establishing) +++ pgbench -n -f /home/florisvannee/workspace/pg_dev/limit/test_fwd_eq.sql -T 20 postgres -Dnitems=1000 transaction type: /home/florisvannee/workspace/pg_dev/limit/test_fwd_eq.sql scaling factor: 1 query mode: simple number of clients: 1 number of threads: 1 duration: 20 s number of transactions actually processed: 7621 latency average = 2.624 ms tps = 381.043284 (including connections establishing) tps = 381.093124 (excluding connections establishing) +++ pgbench -n -f /home/florisvannee/workspace/pg_dev/limit/test_fwd_single.sql -T 20 postgres -Dnlimit=1 transaction type: /home/florisvannee/workspace/pg_dev/limit/test_fwd_single.sql scaling factor: 1 query mode: simple number of clients: 1 number of threads: 1 duration: 20 s number of transactions actually processed: 229991 latency average = 0.087 ms tps = 11499.514293 (including connections establishing) tps = 11501.125904 (excluding connections establishing) +++ pgbench -n -f /home/florisvannee/workspace/pg_dev/limit/test_fwd_single.sql -T 20 postgres -Dnlimit=3 transaction type: /home/florisvannee/workspace/pg_dev/limit/test_fwd_single.sql scaling factor: 1 query mode: simple number of clients: 1 number of threads: 1 duration: 20 s number of transactions actually processed: 215881 latency average = 0.093 ms tps = 10794.011481 (including connections establishing) tps = 10794.899742 (excluding connections establishing) +++ pgbench -n -f /home/florisvannee/workspace/pg_dev/limit/test_fwd_single.sql -T 20 postgres -Dnlimit=50 transaction type: /home/florisvannee/workspace/pg_dev/limit/test_fwd_single.sql scaling factor: 1 query mode: simple number of clients: 1 number of threads: 1 duration: 20 s number of transactions actually processed: 173334 latency average = 0.115 ms tps = 8666.645542 (including connections establishing) tps = 8667.882794 (excluding connections establishing) +++ pgbench -n -f /home/florisvannee/workspace/pg_dev/limit/test_fwd.sql -T 20 postgres -Dnitems=10 -Dnlimit=1 transaction type: /home/florisvannee/workspace/pg_dev/limit/test_fwd.sql scaling factor: 1 query mode: simple number of clients: 1 number of threads: 1 duration: 20 s number of transactions actually processed: 117364 latency average = 0.170 ms tps = 5868.162298 (including connections establishing) tps = 5868.966227 (excluding connections establishing) +++ pgbench -n -f /home/florisvannee/workspace/pg_dev/limit/test_fwd.sql -T 20 postgres -Dnitems=100 -Dnlimit=1 transaction type: /home/florisvannee/workspace/pg_dev/limit/test_fwd.sql scaling factor: 1 query mode: simple number of clients: 1 number of threads: 1 duration: 20 s number of transactions actually processed: 49578 latency average = 0.403 ms tps = 2478.893661 (including connections establishing) tps = 2479.258209 (excluding connections establishing) +++ pgbench -n -f /home/florisvannee/workspace/pg_dev/limit/test_fwd.sql -T 20 postgres -Dnitems=1000 -Dnlimit=1 transaction type: /home/florisvannee/workspace/pg_dev/limit/test_fwd.sql scaling factor: 1 query mode: simple number of clients: 1 number of threads: 1 duration: 20 s number of transactions actually processed: 7897 latency average = 2.533 ms tps = 394.817306 (including connections establishing) tps = 394.874583 (excluding connections establishing) +++ pgbench -n -f /home/florisvannee/workspace/pg_dev/limit/test_fwd.sql -T 20 postgres -Dnitems=10000 -Dnlimit=1 transaction type: /home/florisvannee/workspace/pg_dev/limit/test_fwd.sql scaling factor: 1 query mode: simple number of clients: 1 number of threads: 1 duration: 20 s number of transactions actually processed: 842 latency average = 23.775 ms tps = 42.060903 (including connections establishing) tps = 42.066652 (excluding connections establishing) +++ pgbench -n -f /home/florisvannee/workspace/pg_dev/limit/test_fwd.sql -T 20 postgres -Dnitems=10 -Dnlimit=3 transaction type: /home/florisvannee/workspace/pg_dev/limit/test_fwd.sql scaling factor: 1 query mode: simple number of clients: 1 number of threads: 1 duration: 20 s number of transactions actually processed: 91328 latency average = 0.219 ms tps = 4566.376538 (including connections establishing) tps = 4566.973889 (excluding connections establishing) +++ pgbench -n -f /home/florisvannee/workspace/pg_dev/limit/test_fwd.sql -T 20 postgres -Dnitems=100 -Dnlimit=3 transaction type: /home/florisvannee/workspace/pg_dev/limit/test_fwd.sql scaling factor: 1 query mode: simple number of clients: 1 number of threads: 1 duration: 20 s number of transactions actually processed: 21644 latency average = 0.924 ms tps = 1082.149192 (including connections establishing) tps = 1082.288793 (excluding connections establishing) +++ pgbench -n -f /home/florisvannee/workspace/pg_dev/limit/test_fwd.sql -T 20 postgres -Dnitems=1000 -Dnlimit=3 transaction type: /home/florisvannee/workspace/pg_dev/limit/test_fwd.sql scaling factor: 1 query mode: simple number of clients: 1 number of threads: 1 duration: 20 s number of transactions actually processed: 2575 latency average = 7.769 ms tps = 128.715772 (including connections establishing) tps = 128.734108 (excluding connections establishing) +++ pgbench -n -f /home/florisvannee/workspace/pg_dev/limit/test_fwd.sql -T 20 postgres -Dnitems=10000 -Dnlimit=3 transaction type: /home/florisvannee/workspace/pg_dev/limit/test_fwd.sql scaling factor: 1 query mode: simple number of clients: 1 number of threads: 1 duration: 20 s number of transactions actually processed: 263 latency average = 76.250 ms tps = 13.114679 (including connections establishing) tps = 13.116601 (excluding connections establishing) +++ pgbench -n -f /home/florisvannee/workspace/pg_dev/limit/test_fwd.sql -T 20 postgres -Dnitems=10 -Dnlimit=50 transaction type: /home/florisvannee/workspace/pg_dev/limit/test_fwd.sql scaling factor: 1 query mode: simple number of clients: 1 number of threads: 1 duration: 20 s number of transactions actually processed: 55591 latency average = 0.360 ms tps = 2779.537585 (including connections establishing) tps = 2779.926201 (excluding connections establishing) +++ pgbench -n -f /home/florisvannee/workspace/pg_dev/limit/test_fwd.sql -T 20 postgres -Dnitems=100 -Dnlimit=50 transaction type: /home/florisvannee/workspace/pg_dev/limit/test_fwd.sql scaling factor: 1 query mode: simple number of clients: 1 number of threads: 1 duration: 20 s number of transactions actually processed: 9465 latency average = 2.113 ms tps = 473.205818 (including connections establishing) tps = 473.274649 (excluding connections establishing) +++ pgbench -n -f /home/florisvannee/workspace/pg_dev/limit/test_fwd.sql -T 20 postgres -Dnitems=1000 -Dnlimit=50 transaction type: /home/florisvannee/workspace/pg_dev/limit/test_fwd.sql scaling factor: 1 query mode: simple number of clients: 1 number of threads: 1 duration: 20 s number of transactions actually processed: 1015 latency average = 19.709 ms tps = 50.738310 (including connections establishing) tps = 50.745497 (excluding connections establishing) +++ pgbench -n -f /home/florisvannee/workspace/pg_dev/limit/test_fwd.sql -T 20 postgres -Dnitems=10000 -Dnlimit=50 transaction type: /home/florisvannee/workspace/pg_dev/limit/test_fwd.sql scaling factor: 1 query mode: simple number of clients: 1 number of threads: 1 duration: 20 s number of transactions actually processed: 103 latency average = 194.247 ms tps = 5.148077 (including connections establishing) tps = 5.148805 (excluding connections establishing)
+++++ dirname ./test_limit.sh ++++ cd . ++++ pwd +++ DIR=/home/florisvannee/workspace/pg_dev/limit +++ T=20 +++ /home/florisvannee/workspace/pg_dev/start.sh master ++++ [[ 1 -eq 2 ]] ++++ [[ 1 -eq 1 ]] ++++ bdir=/home/florisvannee/workspace/postgres ++++ totaldir=master-release ++++ cd /home/florisvannee/workspace/postgres ++++ /home/florisvannee/install/master-release/bin/pg_ctl -D/home/florisvannee/pgdata/master-release -l /home/florisvannee/pgdata/master-release/logfile -t 5 stop pg_ctl: could not send stop signal (PID: 29950): No such process ++++ pkill -9 postgres ++++ /home/florisvannee/install/master-release/bin/pg_ctl -D/home/florisvannee/pgdata/master-release -l /home/florisvannee/pgdata/master-release/logfile start pg_ctl: another server might be running; trying to start server anyway waiting for server to start.... done server started +++ pgbench -n -f /home/florisvannee/workspace/pg_dev/limit/test_fwd_eq.sql -T 20 postgres -Dnitems=1 transaction type: /home/florisvannee/workspace/pg_dev/limit/test_fwd_eq.sql scaling factor: 1 query mode: simple number of clients: 1 number of threads: 1 duration: 20 s number of transactions actually processed: 154896 latency average = 0.129 ms tps = 7744.777852 (including connections establishing) tps = 7745.481275 (excluding connections establishing) +++ pgbench -n -f /home/florisvannee/workspace/pg_dev/limit/test_fwd_eq.sql -T 20 postgres -Dnitems=10 transaction type: /home/florisvannee/workspace/pg_dev/limit/test_fwd_eq.sql scaling factor: 1 query mode: simple number of clients: 1 number of threads: 1 duration: 20 s number of transactions actually processed: 130189 latency average = 0.154 ms tps = 6509.413300 (including connections establishing) tps = 6510.194847 (excluding connections establishing) +++ pgbench -n -f /home/florisvannee/workspace/pg_dev/limit/test_fwd_eq.sql -T 20 postgres -Dnitems=100 transaction type: /home/florisvannee/workspace/pg_dev/limit/test_fwd_eq.sql scaling factor: 1 query mode: simple number of clients: 1 number of threads: 1 duration: 20 s number of transactions actually processed: 51467 latency average = 0.389 ms tps = 2573.330950 (including connections establishing) tps = 2573.706453 (excluding connections establishing) +++ pgbench -n -f /home/florisvannee/workspace/pg_dev/limit/test_fwd_eq.sql -T 20 postgres -Dnitems=1000 transaction type: /home/florisvannee/workspace/pg_dev/limit/test_fwd_eq.sql scaling factor: 1 query mode: simple number of clients: 1 number of threads: 1 duration: 20 s number of transactions actually processed: 7820 latency average = 2.558 ms tps = 390.956588 (including connections establishing) tps = 391.013884 (excluding connections establishing) +++ pgbench -n -f /home/florisvannee/workspace/pg_dev/limit/test_fwd_single.sql -T 20 postgres -Dnlimit=1 transaction type: /home/florisvannee/workspace/pg_dev/limit/test_fwd_single.sql scaling factor: 1 query mode: simple number of clients: 1 number of threads: 1 duration: 20 s number of transactions actually processed: 219722 latency average = 0.091 ms tps = 10986.053856 (including connections establishing) tps = 10987.598953 (excluding connections establishing) +++ pgbench -n -f /home/florisvannee/workspace/pg_dev/limit/test_fwd_single.sql -T 20 postgres -Dnlimit=3 transaction type: /home/florisvannee/workspace/pg_dev/limit/test_fwd_single.sql scaling factor: 1 query mode: simple number of clients: 1 number of threads: 1 duration: 20 s number of transactions actually processed: 215711 latency average = 0.093 ms tps = 10785.486753 (including connections establishing) tps = 10786.586186 (excluding connections establishing) +++ pgbench -n -f /home/florisvannee/workspace/pg_dev/limit/test_fwd_single.sql -T 20 postgres -Dnlimit=50 transaction type: /home/florisvannee/workspace/pg_dev/limit/test_fwd_single.sql scaling factor: 1 query mode: simple number of clients: 1 number of threads: 1 duration: 20 s number of transactions actually processed: 174473 latency average = 0.115 ms tps = 8723.607124 (including connections establishing) tps = 8724.854159 (excluding connections establishing) +++ pgbench -n -f /home/florisvannee/workspace/pg_dev/limit/test_fwd.sql -T 20 postgres -Dnitems=10 -Dnlimit=1 transaction type: /home/florisvannee/workspace/pg_dev/limit/test_fwd.sql scaling factor: 1 query mode: simple number of clients: 1 number of threads: 1 duration: 20 s number of transactions actually processed: 93067 latency average = 0.215 ms tps = 4653.322050 (including connections establishing) tps = 4654.022097 (excluding connections establishing) +++ pgbench -n -f /home/florisvannee/workspace/pg_dev/limit/test_fwd.sql -T 20 postgres -Dnitems=100 -Dnlimit=1 transaction type: /home/florisvannee/workspace/pg_dev/limit/test_fwd.sql scaling factor: 1 query mode: simple number of clients: 1 number of threads: 1 duration: 20 s number of transactions actually processed: 23328 latency average = 0.857 ms tps = 1166.383516 (including connections establishing) tps = 1166.560584 (excluding connections establishing) +++ pgbench -n -f /home/florisvannee/workspace/pg_dev/limit/test_fwd.sql -T 20 postgres -Dnitems=1000 -Dnlimit=1 transaction type: /home/florisvannee/workspace/pg_dev/limit/test_fwd.sql scaling factor: 1 query mode: simple number of clients: 1 number of threads: 1 duration: 20 s number of transactions actually processed: 2823 latency average = 7.086 ms tps = 141.115678 (including connections establishing) tps = 141.135409 (excluding connections establishing) +++ pgbench -n -f /home/florisvannee/workspace/pg_dev/limit/test_fwd.sql -T 20 postgres -Dnitems=10000 -Dnlimit=1 transaction type: /home/florisvannee/workspace/pg_dev/limit/test_fwd.sql scaling factor: 1 query mode: simple number of clients: 1 number of threads: 1 duration: 20 s number of transactions actually processed: 292 latency average = 68.710 ms tps = 14.553922 (including connections establishing) tps = 14.555983 (excluding connections establishing) +++ pgbench -n -f /home/florisvannee/workspace/pg_dev/limit/test_fwd.sql -T 20 postgres -Dnitems=10 -Dnlimit=3 transaction type: /home/florisvannee/workspace/pg_dev/limit/test_fwd.sql scaling factor: 1 query mode: simple number of clients: 1 number of threads: 1 duration: 20 s number of transactions actually processed: 90974 latency average = 0.220 ms tps = 4548.655001 (including connections establishing) tps = 4549.337781 (excluding connections establishing) +++ pgbench -n -f /home/florisvannee/workspace/pg_dev/limit/test_fwd.sql -T 20 postgres -Dnitems=100 -Dnlimit=3 transaction type: /home/florisvannee/workspace/pg_dev/limit/test_fwd.sql scaling factor: 1 query mode: simple number of clients: 1 number of threads: 1 duration: 20 s number of transactions actually processed: 22080 latency average = 0.906 ms tps = 1103.982784 (including connections establishing) tps = 1104.122082 (excluding connections establishing) +++ pgbench -n -f /home/florisvannee/workspace/pg_dev/limit/test_fwd.sql -T 20 postgres -Dnitems=1000 -Dnlimit=3 transaction type: /home/florisvannee/workspace/pg_dev/limit/test_fwd.sql scaling factor: 1 query mode: simple number of clients: 1 number of threads: 1 duration: 20 s number of transactions actually processed: 2630 latency average = 7.606 ms tps = 131.467656 (including connections establishing) tps = 131.486783 (excluding connections establishing) +++ pgbench -n -f /home/florisvannee/workspace/pg_dev/limit/test_fwd.sql -T 20 postgres -Dnitems=10000 -Dnlimit=3 transaction type: /home/florisvannee/workspace/pg_dev/limit/test_fwd.sql scaling factor: 1 query mode: simple number of clients: 1 number of threads: 1 duration: 20 s number of transactions actually processed: 271 latency average = 73.890 ms tps = 13.533643 (including connections establishing) tps = 13.535616 (excluding connections establishing) +++ pgbench -n -f /home/florisvannee/workspace/pg_dev/limit/test_fwd.sql -T 20 postgres -Dnitems=10 -Dnlimit=50 transaction type: /home/florisvannee/workspace/pg_dev/limit/test_fwd.sql scaling factor: 1 query mode: simple number of clients: 1 number of threads: 1 duration: 20 s number of transactions actually processed: 56385 latency average = 0.355 ms tps = 2819.202652 (including connections establishing) tps = 2819.611918 (excluding connections establishing) +++ pgbench -n -f /home/florisvannee/workspace/pg_dev/limit/test_fwd.sql -T 20 postgres -Dnitems=100 -Dnlimit=50 transaction type: /home/florisvannee/workspace/pg_dev/limit/test_fwd.sql scaling factor: 1 query mode: simple number of clients: 1 number of threads: 1 duration: 20 s number of transactions actually processed: 9744 latency average = 2.053 ms tps = 487.182328 (including connections establishing) tps = 487.247681 (excluding connections establishing) +++ pgbench -n -f /home/florisvannee/workspace/pg_dev/limit/test_fwd.sql -T 20 postgres -Dnitems=1000 -Dnlimit=50 transaction type: /home/florisvannee/workspace/pg_dev/limit/test_fwd.sql scaling factor: 1 query mode: simple number of clients: 1 number of threads: 1 duration: 20 s number of transactions actually processed: 1050 latency average = 19.059 ms tps = 52.469680 (including connections establishing) tps = 52.477479 (excluding connections establishing) +++ pgbench -n -f /home/florisvannee/workspace/pg_dev/limit/test_fwd.sql -T 20 postgres -Dnitems=10000 -Dnlimit=50 transaction type: /home/florisvannee/workspace/pg_dev/limit/test_fwd.sql scaling factor: 1 query mode: simple number of clients: 1 number of threads: 1 duration: 20 s number of transactions actually processed: 107 latency average = 187.881 ms tps = 5.322504 (including connections establishing) tps = 5.323249 (excluding connections establishing)
test_fwd.sql
Description: test_fwd.sql
test_fwd_eq.sql
Description: test_fwd_eq.sql
test_fwd_single.sql
Description: test_fwd_single.sql