Run Vectorized Queries
When handling large datasets, the vectorization execution engine can greatly improve computing efficiency. By vectorizing data, multiple data elements can be processed at the same time, using parallel computing and SIMD instruction sets to speed up the process. SynxDB Vectorization (referred to as Vectorization) is a vectorization plugin based on the SynxDB kernel, designed to optimize query performance.
Enable vectorization
Before enabling SynxDB Vectorization, you need to install and deploy SynxDB.
Connect to the target database. Replace
your_database_namewith the actual name of your database.$ psql your_database_name;
Enable vectorization in the database.
SET vector.enable_vectorization = ON;
Usage
Vectorization provides the following parameters for users:
Parameter name |
Description |
|---|---|
|
Controls whether vectorized queries are enabled. It is disabled by default. |
|
The size of the vectorized batch, which controls how many rows the executor processes in one cycle. The range is |
|
Memory budget in MB for the hash join build side. When the estimated hash table size exceeds this value, data is spilled to disk and processed in partitions. The range is |
|
Maximum |
|
Whether to skip PAX row groups whose column min/max falls outside the current |
|
Upper bound on |
|
Controls whether a vectorized hash aggregate routes its output batches directly to the redistribute Motion, skipping per-row rehashing. Disabled by default ( |
|
Memory budget in MB for |
Enable or disable vectorization queries
You can temporarily enable or disable the vectorization feature in a connection by setting the vector.enable_vectorization variable. This setting is effective only for the current connection, and it will reset to the default value after disconnecting.
After uninstalling vectorization, setting the vector.enable_vectorization variable will have no effect. When you reinstall it, the vector.enable_vectorization will be restored to the default value off.
SET vector.enable_vectorization TO [on|off];
Set vectorization batch size
The batch size of vectorization greatly affects performance. If the value is too small, queries might slow down. If the value is too large, it might increase memory usage without improving performance.
SET vector.max_batch_size TO <batch_number>;
Set hash join spill memory budget
Note
This parameter only takes effect when vectorization is enabled.
When a vectorized hash join processes a large build side that exceeds available memory, it can cause out-of-memory failures. The vector.hashjoin_spill_memory_mb parameter controls the memory budget for the hash join build side. When the estimated hash table size exceeds this budget, data is automatically spilled to disk and processed in partitions, preventing out-of-memory failures on large hash joins.
The default value is 512 MB, which is suitable for most workloads. You can increase this value if your system has sufficient memory and you want to reduce disk spills, or decrease it to conserve memory in resource-constrained environments. Setting it to 0 disables spill-to-disk entirely.
-- Set the hash join spill memory budget to 1024 MB.
SET vector.hashjoin_spill_memory_mb = 1024;
-- Disable spill-to-disk (not recommended for large hash joins).
SET vector.hashjoin_spill_memory_mb = 0;
Speed up ORDER BY … LIMIT N with TopK
Note
This parameter only takes effect when vectorization is enabled.
For ORDER BY ... LIMIT N queries, the vectorized executor can replace a full sort with a TopK operator that maintains a bounded heap of the best N rows. Only rows that beat the heap’s current worst value are kept, so the executor never materializes a full sorted set.
The vector.topk_bound_threshold parameter controls when the executor applies this replacement. When LIMIT + OFFSET is less than or equal to the threshold (default 2000), the executor builds a TopK node. For larger values, or when the plan shape is Limit → Result → Sort, the executor falls back to a full sort followed by row selection.
A non-zero OFFSET produces the Limit → Result → Sort plan shape, so a query that uses OFFSET falls back to a full sort even when LIMIT + OFFSET stays within the threshold. In practice, TopK applies to LIMIT-only queries.
To raise or lower the boundary, set the parameter for the current session:
-- Allow TopK for LIMIT values up to 5000.
SET vector.topk_bound_threshold = 5000;
-- Disable the TopK plan optimization.
SET vector.topk_bound_threshold = 0;
To confirm that a query runs with TopK, use EXPLAIN and look for a Vec Sort Method line under the Sort node:
gpadmin=# EXPLAIN SELECT * FROM events ORDER BY ts DESC LIMIT 100;
QUERY PLAN
--------------------------------------------------------------------------
Vec Limit (cost=...)
-> Vec Gather Motion 3:1 (slice1; segments: 3) (cost=...)
-> Vec Sort (cost=...)
Sort Key: ts DESC
Vec Sort Method: TopK K: 100
-> Vec Seq Scan on events (cost=...)
If the Vec Sort Method line is absent, the query is using OrderByNode instead, either because LIMIT + OFFSET exceeds the threshold or because the plan shape is ineligible.
Skip PAX row groups for TopK queries
Note
This parameter only takes effect on PAX tables with vectorization enabled.
For ORDER BY ... LIMIT N queries that run under the vectorized executor, the TopK operator keeps a heap of the best N rows seen so far. The vector.topk_runtime_filter parameter lets the executor push the heap’s current worst value down to the PAX scan as a runtime threshold. The scan then compares each row group’s stored column min/max statistics against the threshold and skips any group whose values cannot improve the top N result, avoiding I/O on those groups entirely.
The parameter is on by default. Turn it off when you need to diagnose a result discrepancy or compare execution without group-level skipping:
-- Disable group-level skip for the current session.
SET vector.topk_runtime_filter = off;
The filter applies only when the sort key resolves to a base table column whose min/max statistics PAX tracks. Queries whose sort expression references a computed value, or whose plan shape prevents the executor from mapping the sort column back to a base table column, scan all row groups.
Hash aggregate execution engines
The vectorized executor runs hash aggregation on one of two engines: a default fast-path engine (referred to as Sonic in EXPLAIN output) for most analytic aggregations, and a legacy engine (referred to as Normal) for queries that fall outside the fast-path’s supported set or that trigger a specialized routing rule. Both engines return identical results; only execution speed differs.
The executor routes a query to the Normal engine when any of the following applies:
The query uses the Limit+HashAgg early-stop optimization. See Speed up top-N group queries with Limit+HashAgg early stop.
The query is a
GROUP BYwithout aggregate functions, or aSELECT DISTINCT.A group-key column is of a type not yet supported by the fast-path engine. The fast-path engine currently supports
smallint,integer,bigint,date,time,timestamp,text,bytea, andnumeric.An aggregate function is not yet supported by the fast-path engine. Currently supported:
count,sumover integer ornumericcolumns,minovertextorbyteacolumns, andavgovernumericcolumns.
For a numeric column to participate in vectorized aggregation, whether as a group key or as an aggregate input, the column must be declared with an explicit precision and scale (for example, numeric(20, 4)). A numeric column declared without them is not vectorized, and the whole query runs on the row engine.
In a distributed query, hash aggregation runs in two stages: a partial stage on each segment, and a finalize stage after redistribution. EXPLAIN VERBOSE reports a Vec HashAgg Method: line for each stage, so a single query can show different engines for its two stages. In particular, when the query aggregates with sum over a numeric column, the finalize stage runs on the Normal engine even though the partial stage uses the fast-path engine. sum over integer columns and avg over numeric columns use the fast-path engine in both stages.
To check which engine handles a hash aggregate, run EXPLAIN VERBOSE and look for the Vec HashAgg Method: line under the Vec HashAggregate node:
EXPLAIN VERBOSE SELECT key, count(*) FROM t GROUP BY key;
The value is one of Sonic (fast path), Normal (legacy path), or Limit+HashAgg (legacy path with the early-stop bound applied).
Speed up top-N group queries with Limit+HashAgg early stop
When a GROUP BY query feeds directly into a LIMIT clause without an ORDER BY in between, the vectorized executor can stop aggregating once it has produced the first N groups, instead of building the complete hash table over all input. This early-stop path delivers roughly a 3x speedup on “top-N by group” workloads such as TPC-H Q18.
The vector.limit_hashagg_max_total parameter sets the upper bound on OFFSET + LIMIT for which the optimization is applied. The default value is 1000; the hard ceiling is 10000, beyond which the per-group tracking overhead outweighs the early-stop benefit. Setting the parameter to 0 disables the optimization. The executor applies it automatically when all of the following conditions hold:
The aggregation uses the HashAgg strategy.
The
LIMIToperator is the direct parent of the HashAgg (noORDER BYor other operator in between).Both
LIMITand anyOFFSETare constant integer literals, not parameters or expressions.OFFSET + LIMITis between 1 and the value ofvector.limit_hashagg_max_total.
When any condition is not met, the query falls back to the standard vectorized HashAgg path and returns identical results without the early-stop benefit. To disable the optimization, for example to compare execution time or to diagnose a plan, set the parameter to 0:
-- Disable Limit+HashAgg early stop for the current session.
SET vector.limit_hashagg_max_total = 0;
-- Raise the threshold to allow early stop on larger top-N queries.
SET vector.limit_hashagg_max_total = 5000;
Queries that take this path run on the Normal engine (see Hash aggregate execution engines), because the fast-path engine does not yet honor the early-stop bound.
Reduce cross-segment latency with direct-send routing
For distributed analytic queries that redistribute the result of a hash aggregation across segments, the vectorized executor can attach a segment tag to each output batch inside the hash aggregate, allowing the Motion operator to forward the batch as-is instead of rehashing every row. This direct-send routing reduces the per-row overhead of cross-segment data movement and lowers latency on queries that span segments. The optimization applies only on the Sonic engine path (see Hash aggregate execution engines).
The vector.sonic_motion_direct_send parameter controls this optimization and is disabled by default. To opt in for the current session:
SET vector.sonic_motion_direct_send = on;
The executor applies the optimization automatically when all of the following conditions hold:
The query uses a hash redistribute Motion directly above a vectorized hash aggregate.
The cluster has more than one segment.
Every column in the redistribution key is one of the supported types:
smallint,integer,bigint,text,timestamp,time, ordate.The redistribution key is a subset of the
GROUP BYcolumns. Redistribution on an aggregate result (for example,SUM(x)) is not currently supported.
When any condition is not met, the query falls back to standard hash redistribution and returns identical results without the latency benefit.
To check whether direct-send applies to a query, look for Direct Send: yes in the EXPLAIN output on the corresponding Motion node:
EXPLAIN SELECT key, count(*) FROM t GROUP BY key;
When the GUC is on and the query plan matches the required structure, the Motion line shows Direct Send: yes. The annotation reflects only the conditions visible at plan time, so the runtime executor might still fall back, for example, when a column type is not supported.
Execution methods for window functions
With vectorization enabled, window functions run in one of two ways: sort-based window aggregation (Vec WindowAgg) or hash-based window aggregation (Vec WindowHashAgg). The optimizer chooses between them as follows:
When every window in the query has a
PARTITION BY, the optimizer uses sort-based window aggregation by default. If the query also carries a Top-K qualification, that is,<=or<constrains the output ofrank(),dense_rank(), orrow_number(), the plan includesVec Partition Top-K, which prunes each partition down to its candidate rows before sorting.vector.enable_partition_topkcontrols this behavior and defaults toon.When a window has no
PARTITION BY, the optimizer uses hash-based window aggregation by default.
vector.enable_window_hash_agg controls whether the optimizer can use hash-based window aggregation. It defaults to on. When you set it to off, all window functions use sort-based window aggregation.
Warning
Under hash-based window aggregation, rank() can return wrong ranks without raising an error. The problem appears when many rows take part in the window computation (about 200,000 rows or more). The problem does not affect row_number(), dense_rank(), percent_rank(), or aggregate window functions.
For queries that use rank(), disable hash-based window aggregation in the session, and keep vector.enable_partition_topk at its default value of on:
SET vector.enable_window_hash_agg = off;
You can check which execution method a window function uses in the EXPLAIN output. The window in the following query has a PARTITION BY and a Top-K qualification, so it uses sort-based window aggregation with Vec Partition Top-K:
EXPLAIN (COSTS OFF)
SELECT * FROM (
SELECT g, k, rank() OVER (PARTITION BY g ORDER BY v DESC) AS r FROM t
) s WHERE r <= 3;
QUERY PLAN
---------------------------------------------------------
Vec Gather Motion 2:1 (slice1; segments: 2)
-> Vec Result
Filter: ((rank() OVER (?)) <= 3)
-> Vec WindowAgg
Partition By: g
Order By: v
-> Vec Sort
Sort Key: g, v DESC
-> Vec Partition Top-K
-> Vec Seq Scan on t
Optimizer: GPORCA
Set window aggregate spill memory budget
Note
This parameter only takes effect when vectorization and the GPORCA optimizer are enabled, because the WindowHashAgg operator is generated only by GPORCA. With the PostgreSQL-based planner (optimizer = off), window aggregation uses a sort-based plan and this parameter has no effect.
A vectorized window aggregate (WindowHashAgg) over a large partition set can exceed available memory and cause out-of-memory failures. The vector.winagg_spill_memory_mb parameter controls the memory budget for window aggregation. When the estimated working memory exceeds this budget, data is automatically spilled to disk and processed in partitions, preventing out-of-memory failures on large window queries.
The default value is 512 MB, which is suitable for most workloads. You can increase this value if your system has sufficient memory and you want to reduce disk spills, or decrease it to conserve memory in resource-constrained environments. Setting it to 0 disables spill-to-disk entirely. Because this budget is independent of the hash join spill budget, you can size window aggregate spill separately from other operators in the same query.
-- Set the window aggregate spill memory budget to 1024 MB.
SET vector.winagg_spill_memory_mb = 1024;
-- Disable spill-to-disk (not recommended for large window queries).
SET vector.winagg_spill_memory_mb = 0;
Use vectorized scans on foreign tables
ORC and Parquet foreign tables created with datalake_fdw can use vectorized scans. Enable vectorization in the session; the foreign table itself needs no extra setting:
SET vector.enable_vectorization = on;
Foreign tables in other formats, including CSV, text, and Avro, stay on the row engine and raise no error.
Supported column types
A query is vectorized when every column it references has one of these types: smallint, integer, bigint, real, double precision, numeric, date, timestamp, text, varchar, char, and boolean.
A numeric column has two further requirements:
A
numericcolumn in a Parquet foreign table must declare its precision and scale. Without them, the table creation itself fails withThe precision of numeric in foreign tables with parquet format should be specified explicitly.The precision cannot exceed 35.
When a query references a column outside that range, such as a timestamptz column, the whole query falls back to the row engine. The result stays the same, only without the speedup. The decision covers the columns the query actually references, so a table that holds an unsupported column can still be scanned with vectorization as long as the query leaves that column out.
Confirm whether a foreign table query is vectorized
The scan node of a foreign table always appears as Foreign Scan in the EXPLAIN output, without a Vec prefix. Read the nodes above it instead:
gpadmin=# EXPLAIN SELECT count(*) FROM sales_parquet WHERE amount > 100;
QUERY PLAN
----------------------------------------------------------------------------------------
Vec Aggregate (cost=0.00..431.00 rows=1 width=8)
-> Vec Gather Motion 2:1 (slice1; segments: 2) (cost=0.00..431.00 rows=1 width=1)
-> Foreign Scan on sales_parquet (cost=0.00..431.00 rows=1 width=1)
Filter: (amount > 100)
Optimizer: GPORCA
(5 rows)
To see why a query falls back to the row engine, turn on the fallback log in the session:
SET vector.print_fallback_log = on;
SET client_min_messages = log;
The server then prints one log line per fallback reason when you run the query, for example Fallback to non-vectorization: numeric type precision 38 not support.
Restrictions on numeric columns in ORC foreign tables
Warning
With vectorization on, a numeric column in an ORC foreign table returns wrong values. The decimal places are dropped and the value is scaled up, so a column with scale 2 reads 0.01 as 1. The query raises no error, and both filter conditions and aggregate results are wrong. A numeric column with scale 0 is unaffected, and so are Parquet foreign tables.
Turn vectorization off in the session before you query a numeric column with a scale above 0 in an ORC foreign table. To use vectorization on such data, store it as Parquet instead.
Also, when the ORC file stores a numeric column with a precision above 35 and the foreign table declares the column with a precision of 35 or less, the segment process crashes once vectorization is on, which interrupts every session on that segment. Declare the column with the precision the file actually uses.
Verify whether a query is vectorized
You can use EXPLAIN to check whether a query is a vectorization query.
If the first line of the
QUERY PLANhas a “Vec” label, it means the query uses vectorization.gpadmin=# EXPLAIN SELECT * FROM int8_tbl; QUERY PLAN ----------------------------------------------------------------------------------- Vec Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=16) -> Vec Seq Scan on int8_tbl (cost=0.00..431.00 rows=1 width=16) Optimizer: Pivotal Optimizer (GPORCA) (3 rows)
If the first line of the
QUERY PLANdoes not have a “Vec” label, it means the query does not use vectorization.gpadmin=# EXPLAIN SELECT * FROM int8_tbl; QUERY PLAN ------------------------------------------------------------------------------- Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=16) -> Seq Scan on int8_tbl (cost=0.00..431.00 rows=1 width=16) Optimizer: Pivotal Optimizer (GPORCA) (3 rows)
Features supported by vectorization
Feature |
Supported or not |
Description |
|---|---|---|
Storage format |
Supported |
AOCS, PAX, and ORC and Parquet foreign tables created with |
Storage format |
Not supported |
HEAP |
Data types |
Supported |
int2, int4, int8, float8, bool, char, tid, date, time, timestamp, timestamptz, varchar, text, numeric |
Data types |
Not supported |
Custom type |
Scan operator |
Supported |
Scanning AOCS tables, PAX tables, and ORC and Parquet foreign tables, complex filter conditions |
Scan operator |
Not supported |
HEAP tables |
Agg operator |
Supported |
Aggregate functions: min, max, count, sum, avg, stddev_samp (integer columns only) Aggregation plans: PlanAggregate (simple aggregate), GroupAggregate (sorted aggregate), HashAggregate (hash aggregate) |
Agg operator |
Not Supported |
Aggregate functions: stddev, stddev_pop (standard deviation), stddev_samp on columns of types other than integer, variance, var_samp, var_pop (variance) Aggregation plans: MixedAggregate (mixed aggregate) |
Limit operator |
Supported |
All |
ForeignScan operator |
Supported |
All |
Result operator |
Supported |
All |
Append operator |
Supported |
All |
Subquery operator |
Supported |
All |
Sequence operator |
Supported |
All |
NestedLoopJoin operator |
Supported |
Join types: inner join, left join, semi join, anti join |
NestedLoopJoin operator |
Not supported |
Join types: right join, full join, semi-anti join Join conditions: different data types, complex inequality conditions |
Material operator |
Supported |
All |
ShareInputScan operator |
Supported |
All |
ForeignScan operator |
Supported |
All |
HashJoin operator |
Supported |
Join types: inner join, left join, right join, full join, semi join, anti join, semi-anti join |
HashJoin operator |
Not Supported |
Join conditions: different data types, complex inequality conditions |
Sort operator |
Supported |
Sorting order: ascending, descending algorithms: order by, order by limit |
WindowAgg operator |
Supported |
Supports sort-based window aggregation ( |
Motion operator |
Supported |
GATHER (sending tuples from multiple senders to one receiver), GATHER_SINGLE (single-node gathering), HASH (simple hash conditions), BROADCAST (broadcast gathering), EXPLICIT (explicit gathering) |
Motion operator |
Not supported |
Hash gathering (complex hash conditions) |
Expressions |
Supported |
case when, is distinct, is not distinct, grouping, groupid, abs, round, upper, textcat, date_pli, coalesce, substr, date_trunc |
date_trunc function |
Supported |
|
date_trunc function |
Not supported |
The query falls back to row-based execution, with identical results, when any of the following applies: the |
Bench |
Supported |
ClickHouse, TPC-H, TPC-DS, ICW, ICW-ORCA |
Threaded execution on single node
By performing threaded parallel computation within the execution node, better utilization of multi-core machine resources can be achieved, reducing query time and improving query performance. The following vectorized operators support threaded acceleration:
Scan (Filter)
Join
Agg
Sort
Currently, the vectorized query feature supports enabling threaded queries in a single-node deployment. To enable it, the following GUC values need to be configured:
set vector.enable_vectorization=on; -- Enable vectorized query
set vector.enable_plan_merge=on; -- Enable Pipeline scheduling execution
set vector.pool_threads=8; -- Configure the number of execution threads
Setting vector.pool_threads to 1 is treated as 0, which disables the thread pool. A one-thread pool has no second thread to drain its own queue, so that value is not usable. Set it to at least 2 for threaded execution.
Vectorized threaded execution relies on the underlying PAX storage file format. Take the tpcds PAX table store_sales as an example. When threaded execution is not enabled:
gpadmin=# set vector.pool_threads=0;
SET
gpadmin=# explain analyse select ss_quantity from store_sales
where ss_quantity between 6 and 10 and ss_list_price between 5 and 5+10;
QUERY PLAN
------------------------------------------------------------------------------------------------------------
---------------------------------
Vec Seq Scan on store_sales (cost=0.00..661957.82 rows=28801 width=4) (actual time=8804.432..8805.236 rows
=94117 loops=1)
Filter: ((ss_quantity >= 6) AND (ss_quantity <= 10) AND (ss_list_price >= '5'::numeric(15,2)) AND (ss_lis
t_price <= '15'::numeric(15,2)))
Planning Time: 0.475 ms
(slice0) Executor memory: 114K bytes.
Memory used: 128000kB
Optimizer: Postgres query optimizer
Execution Time: 8809.841 ms
(7 rows)
When threaded execution is enabled and the pool_threads parameter is set to 8:
gpadmin=# set vector.pool_threads=8;
SET
gpadmin=# explain analyse select ss_quantity from store_sales
where ss_quantity between 6 and 10 and ss_list_price between 5 and 5+10;
QUERY PLAN
------------------------------------------------------------------------------------------------------------
---------------------------------
After enabling threaded queries, the query time is significantly reduced.
Performance evaluation
TPC-H
There are 22 query SQL statements in TPC-H. Compared to non-vectorized execution, vectorization improves the overall performance by 2 times or more. For pure aggregation SQL statements, vectorization can speed up the process by 3 times or more compared to non-vectorized execution.
Statement |
Query time without vec (s) |
Query time with vec (s) |
Time diff (s) = non-vec - vec |
Improvement (times) |
|---|---|---|---|---|
1 |
54 |
18 |
36 |
3 |
2 |
9 |
3 |
6 |
3 |
3 |
23 |
14 |
9 |
1.64 |
4 |
44 |
22 |
22 |
2 |
5 |
28 |
11 |
17 |
2.54 |
6 |
10 |
7 |
3 |
1.43 |
7 |
22 |
13 |
9 |
1.69 |
8 |
28 |
11 |
17 |
2.55 |
9 |
62 |
21 |
41 |
2.95 |
10 |
22 |
12 |
10 |
1.83 |
11 |
5 |
5 |
0 |
1 |
12 |
15 |
11 |
4 |
1.36 |
13 |
28 |
13 |
15 |
2.15 |
14 |
10 |
7 |
3 |
1.43 |
15 |
12 |
7 |
5 |
1.71 |
16 |
7 |
4 |
3 |
1.75 |
17 |
92 |
20 |
72 |
4.6 |
18 |
79 |
20 |
59 |
3.95 |
19 |
13 |
13 |
0 |
1 |
20 |
23 |
13 |
10 |
1.77 |
21 |
72 |
61 |
11 |
1.15 |
22 |
18 |
18 |
0 |
1 |
Total |
676 |
324 |
352 |
2.09 |
TPC-DS
TPC-DS has 99 query SQL statements, tested in a 1T data environment. Compared to non-vectorized execution, vectorization improves the overall performance by 2 times or more.
Statement |
Query time without vec (s) |
Query time with vec (s) |
Time diff (s) = non-vec - vec |
Improvement (times) |
|---|---|---|---|---|
1 |
5 |
2 |
3 |
2.50 |
2 |
10 |
4 |
6 |
2.50 |
3 |
5 |
2 |
3 |
2.50 |
4 |
41 |
19 |
22 |
2.16 |
5 |
11 |
11 |
0 |
1.00 |
6 |
10 |
4 |
6 |
2.50 |
7 |
12 |
4 |
8 |
3.00 |
8 |
13 |
8 |
5 |
1.63 |
9 |
11 |
7 |
4 |
1.57 |
10 |
12 |
5 |
7 |
2.40 |
11 |
30 |
14 |
16 |
2.14 |
12 |
3 |
2 |
1 |
1.50 |
13 |
10 |
6 |
4 |
1.67 |
14 |
46 |
37 |
9 |
1.24 |
15 |
10 |
2 |
8 |
5.00 |
16 |
13 |
7 |
6 |
1.86 |
17 |
13 |
5 |
8 |
2.60 |
18 |
15 |
5 |
10 |
3.00 |
19 |
12 |
4 |
8 |
3.00 |
20 |
3 |
2 |
1 |
1.50 |
21 |
6 |
1 |
5 |
6.00 |
22 |
14 |
5 |
9 |
2.80 |
23 |
125 |
43 |
82 |
2.91 |
24 |
147 |
60 |
87 |
2.45 |
25 |
13 |
4 |
9 |
3.25 |
26 |
7 |
2 |
5 |
3.50 |
27 |
11 |
5 |
6 |
2.20 |
28 |
7 |
6 |
1 |
1.17 |
29 |
12 |
4 |
8 |
3.00 |
30 |
11 |
3 |
8 |
3.67 |
31 |
13 |
6 |
7 |
2.17 |
32 |
7 |
2 |
5 |
3.50 |
33 |
10 |
5 |
5 |
2.00 |
34 |
11 |
4 |
7 |
2.75 |
35 |
16 |
5 |
11 |
3.20 |
36 |
10 |
4 |
6 |
2.50 |
37 |
6 |
3 |
3 |
2.00 |
38 |
23 |
7 |
16 |
3.29 |
39 |
25 |
22 |
3 |
1.14 |
40 |
5 |
2 |
3 |
2.50 |
41 |
1 |
1 |
0 |
1.00 |
42 |
5 |
2 |
3 |
2.50 |
43 |
7 |
3 |
4 |
2.33 |
44 |
4 |
4 |
0 |
1.00 |
45 |
12 |
3 |
9 |
4.00 |
46 |
17 |
6 |
11 |
2.83 |
47 |
13 |
7 |
6 |
1.86 |
48 |
8 |
5 |
3 |
1.60 |
49 |
7 |
6 |
1 |
1.17 |
50 |
11 |
3 |
8 |
3.67 |
51 |
11 |
18 |
-7 |
0.61 |
52 |
6 |
2 |
4 |
3.00 |
53 |
7 |
3 |
4 |
2.33 |
54 |
20 |
16 |
4 |
1.25 |
55 |
6 |
2 |
4 |
3.00 |
56 |
9 |
7 |
2 |
1.29 |
57 |
8 |
4 |
4 |
2.00 |
58 |
7 |
4 |
3 |
1.75 |
59 |
19 |
9 |
10 |
2.11 |
60 |
9 |
6 |
3 |
1.50 |
61 |
13 |
5 |
8 |
2.60 |
62 |
4 |
2 |
2 |
2.00 |
63 |
7 |
3 |
4 |
2.33 |
64 |
28 |
13 |
15 |
2.15 |
65 |
18 |
7 |
11 |
2.57 |
66 |
5 |
3 |
2 |
1.67 |
67 |
489 |
205 |
284 |
2.39 |
68 |
16 |
8 |
8 |
2.00 |
69 |
10 |
4 |
6 |
2.50 |
70 |
17 |
16 |
1 |
1.06 |
71 |
9 |
4 |
5 |
2.25 |
72 |
80 |
47 |
33 |
1.70 |
73 |
11 |
4 |
7 |
2.75 |
74 |
25 |
9 |
16 |
2.78 |
75 |
20 |
13 |
7 |
1.54 |
76 |
4 |
4 |
0 |
1.00 |
77 |
9 |
5 |
4 |
1.80 |
78 |
29 |
12 |
17 |
2.42 |
79 |
16 |
6 |
10 |
2.67 |
80 |
11 |
7 |
4 |
1.57 |
81 |
10 |
3 |
7 |
3.33 |
82 |
10 |
4 |
6 |
2.50 |
83 |
3 |
3 |
0 |
1.00 |
84 |
8 |
2 |
6 |
4.00 |
85 |
6 |
3 |
3 |
2.00 |
86 |
4 |
2 |
2 |
2.00 |
87 |
24 |
7 |
17 |
3.43 |
88 |
21 |
8 |
13 |
2.63 |
89 |
7 |
4 |
3 |
1.75 |
90 |
4 |
1 |
3 |
4.00 |
91 |
6 |
2 |
4 |
3.00 |
92 |
6 |
1 |
5 |
6.00 |
93 |
11 |
3 |
8 |
3.67 |
94 |
8 |
5 |
3 |
1.60 |
95 |
66 |
24 |
42 |
2.75 |
96 |
7 |
2 |
5 |
3.50 |
97 |
14 |
5 |
9 |
2.80 |
98 |
6 |
3 |
3 |
2.00 |
99 |
7 |
3 |
4 |
2.33 |
Total |
000 |
916 |
/ |
2.18 |