我在 PostgreSQL 9.4 中有这个表:
CREATE TABLE user_operations(
id SERIAL PRIMARY KEY,
operation_id integer,
user_id integer )
Run Code Online (Sandbox Code Playgroud)
该表由~1000-2000不同的操作组成,每个操作对应于所有用户80000-120000集合S的某个子集(每个子集由大约元素组成):
S = {1, 2, 3, ... , 122655}
Run Code Online (Sandbox Code Playgroud)
参数:
work_mem = 128MB
table_size = 880MB
Run Code Online (Sandbox Code Playgroud)
我也有一个关于operation_id.
问题:user_id对于operation_id集合的重要部分(20%-60%)查询所有不同的最佳计划是什么,例如:
SELECT DISTINCT user_id FROM user_operation WHERE operation_id < 500
Run Code Online (Sandbox Code Playgroud)
可以在表上创建更多索引。目前,查询的计划是:
HashAggregate (cost=196173.56..196347.14 rows=17358 width=4) (actual time=1227.408..1359.947 rows=598336 loops=1)
-> Bitmap Heap Scan on user_operation (cost=46392.24..189978.17 rows=2478155 width=4) (actual time=233.163..611.182 rows=2518122 loops=1)
Recheck Cond: …Run Code Online (Sandbox Code Playgroud) postgresql performance count distinct postgresql-performance
我在 PostgreSQL 9.4 中存储了一个典型的树结构作为邻接列表:
gear_category (
id INTEGER PRIMARY KEY,
name TEXT,
parent_id INTEGER
);
Run Code Online (Sandbox Code Playgroud)
以及附加到类别的项目列表:
gear_item (
id INTEGER PRIMARY KEY,
name TEXT,
category_id INTEGER REFERENCES gear_category
);
Run Code Online (Sandbox Code Playgroud)
任何类别都可以附加装备物品,而不仅仅是树叶。
出于速度原因,我想预先计算有关每个类别的一些数据,我将使用这些数据来生成物化视图。
期望的输出:
speedy_materialized_view (
gear_category_id INTEGER,
count_direct_child_items INTEGER,
count_recursive_child_items INTEGER
);
Run Code Online (Sandbox Code Playgroud)
count_recursive_child_items是附加到当前类别或任何子类别的 GearItems 的累积数量。每个类别应占一行,任何为 0 的计数都为 0。
为了计算这个,我们需要使用递归 CTE 来遍历树:
WITH RECURSIVE children(id, parent_id) AS (
--base case
SELECT gear_category.id AS id, gear_category.parent_id AS parent_id
FROM gear_category
WHERE gear_category.id = 37 -- setting this to id includes current object …Run Code Online (Sandbox Code Playgroud) 目前我们执行两个查询以使用分页过滤器获取计数和结果。虽然我们可以轻松地将这两者结合到一个网络调用中(使用 sql 分隔符),但有没有办法在遵循DRY原则的单个查询中做到这一点?
-- count
SELECT COUNT(*) FROM table;
-- result with pagination
SELECT *
FROM (SELECT ROW_NUMBER() OVER (ORDER BY tbl.idn) AS row, * FROM tbl)_tbl
WHERE row >= 1 AND row <= 10;
Run Code Online (Sandbox Code Playgroud)
维护两个查询真的很有挑战性——单个查询减少了维护开销。
我的应用程序通常需要准确但可能不完美的行数。十亿行的表经常会被频繁写入,所以“完美”是定义和时间的问题。
Microsoft SQL 保留了非常好的元数据,允许进行如下查询:
SELECT SUM(rows) FROM sys.partitions
WHERE object_id = object_id('TABLE_NAME')
AND index_id < 2;
Run Code Online (Sandbox Code Playgroud)
(还有其他具有不同元数据的方法)。这提供了近乎完美的行数,可能会忽略某些正在进行的事务或其他细节。这些技术适用于除最苛刻的情况之外的所有情况,并且几乎是即时的。
在 Oracle 中,我们可以使用统计信息:
SELECT num_rows
FROM all_tables
WHERE table_name = 'TABLE_NAME'
Run Code Online (Sandbox Code Playgroud)
这是不可靠的,因为如果完全收集了统计信息,根据 DBA 策略,它们通常已经过时。
我可以牺牲显着的准确性来使用采样来提高速度:
SELECT COUNT(*) * 1000 rc_sampled FROM lot_size SAMPLE(.1) SEED(42)
Run Code Online (Sandbox Code Playgroud)
然而,这是不准确的设计,还是相当慢(115秒在500M行测试),并且几乎是无用的,当应用程序不已经有一个行数的估计。在一个有 800 行的表上运行该 SQL 就像问,“那个糖果棒的价格是多少,给予或接受 75.00 美元?”)
Oracle 是否提供了一种实用的方法来获得任意表的准确、快速的行数,例如 Microsoft SQL 和其他提供的表?
如果我在这样的表中的行的列中有一个字符串
1 2 2 2 2 2 2
Run Code Online (Sandbox Code Playgroud)
我如何计算字符串2中子字符串的出现次数。假设除了空格分隔符 之外没有其他任何内容" "。
为此,我们将数字视为子字符串
CREATE TABLE foo
AS
SELECT 1 AS id, '1 2 2 2 2 2 2'::text AS data;
TABLE foo
id | data
----+---------------
1 | 1 2 2 2 2 2 2
Run Code Online (Sandbox Code Playgroud) 我的mytable结构如下,我想计算attribute每一行中值的出现次数:
id | attribute
--------------
1 | spam
2 | egg
3 | spam
Run Code Online (Sandbox Code Playgroud)
和
SELECT id, attribute, COUNT(attribute) FROM mytable GROUP BY attribute
Run Code Online (Sandbox Code Playgroud)
我只得到
id | attribute | count
----------------------
1 | spam | 2
2 | egg | 1
Run Code Online (Sandbox Code Playgroud)
但我想要的结果是
id | attribute | count
----------------------
1 | spam | 2
2 | egg | 1
3 | spam | 2
Run Code Online (Sandbox Code Playgroud)
如何实现这一目标?
考虑以下示例:
CREATE TABLE test (
id SERIAL,
some_integer INT
);
INSERT INTO test (some_integer)
SELECT FLOOR(RANDOM()*100000) from generate_series(1,100000) s(i);
CREATE INDEX some_integer_idx ON test (some_integer);
EXPLAIN ANALYZE SELECT COUNT(DISTINCT some_integer) from test;
Run Code Online (Sandbox Code Playgroud)
它返回以下查询计划:
CREATE TABLE test (
id SERIAL,
some_integer INT
);
INSERT INTO test (some_integer)
SELECT FLOOR(RANDOM()*100000) from generate_series(1,100000) s(i);
CREATE INDEX some_integer_idx ON test (some_integer);
EXPLAIN ANALYZE SELECT COUNT(DISTINCT some_integer) from test;
Run Code Online (Sandbox Code Playgroud)
我很惊讶它仍然在测试中进行顺序扫描。简单地计算索引中的行数不是更快吗?
我很难弄清楚如何实现这一目标。我知道如何用 C# 实现它,但不知道如何用 SQL 实现。
假设我有下表:
| ID | 姓名 | 路由ID |
|---|---|---|
| 1 | 鲍勃 | 1001 |
| 2 | 鲍勃 | 1002 |
| 3 | 安娜 | 1001 |
| 4 | 吉姆 | 1001 |
| 5 | 伊莱 | 1001 |
我想返回整个表,并用一个额外的列显示routeID按名称出现的总次数,所以where name='Bob'看起来像:
| ID | 姓名 | 路由ID | 全部的 |
|---|---|---|---|
| 1 | 鲍勃 | 1001 | 4 |
| 2 | 鲍勃 | 1002 | 1 |
但是,如果我写类似的东西
declare @ct as nvarchar(5)
set @ct = (SELECT COUNT(RouteId) from <table>)
select *, @ct
from <table>
where name = 'Bob'
Run Code Online (Sandbox Code Playgroud)
我得到所有路线 ID 的总数,而不仅仅是行中显示的路线 ID。
我尝试查看计算列,但据我所知它不支持这种类型的查询。
有人能指出我正确的方向吗?
我正在尝试优化包含超过 8000 万行的表。需要 20 多分钟才能获得行计数结果。我尝试过集群、vacuum full 和重新索引,但性能没有提高。为了改进数据查询和检索,我需要配置或调整什么?我在 Windows 2019 下使用 Postgresql 12。
更新信息:
Run Code Online (Sandbox Code Playgroud)Explain query result using 'select count(*) from doc_details': Finalize Aggregate (cost=5554120.84..5554120.85 rows=1 width=8) (actual time=1249204.001..1249210.027 rows=1 loops=1) -> Gather (cost=5554120.63..5554120.83 rows=2 width=8) (actual time=1249203.642..1249210.020 rows=3 loops=1) Workers Planned: 2 Workers Launched: 2 -> Partial Aggregate (cost=5553120.63..5553120.63 rows=1 width=8) (actual time=1249153.615..1249153.616 rows=1 loops=3) -> Parallel Seq Scan on doc_details (cost=0.00..5456055.30 rows=38826130 width=0) (actual time=3.793..1245165.604 rows=31018949 loops=3) Planning Time: 1.290 ms Execution Time: …
我有一个events这样的表:
create table events
(
correlation_id char(26) not null,
user_id bigint,
task_id bigint not null,
location_id bigint,
type bigint not null,
created_at timestamp(6) with time zone not null,
constraint events_correlation_id_created_at_user_id_unique
unique (correlation_id, created_at, user_id)
);
Run Code Online (Sandbox Code Playgroud)
Run Code Online (Sandbox Code Playgroud)CREATE TABLE
该表保存正在执行的任务的记录,如下所示:
insert into events (correlation_id, user_id, task_id, location_id, type, created_at)
values ('01CN4HP4AN0000000000000001', 4, 58, 30, 0, '2018-08-17 18:17:15.348629+00'),
('01CN4HP4AN0000000000000001', 4, 58, 30, 1, '2018-08-17 18:17:22.852299+00'),
('01CN4HP4AN0000000000000001', 4, 58, 30, 99, '2018-08-17 18:17:25.535593+00'),
('01CN4J9SZ80000000000000003', 4, 97, 30, 0, '2018-08-17 18:28:00.104093+00'),
('01CN4J9SZ80000000000000003', 4, …Run Code Online (Sandbox Code Playgroud) count ×10
postgresql ×6
distinct ×2
performance ×2
sql-server ×2
aggregate ×1
cte ×1
index ×1
oracle ×1
statistics ×1
string ×1
substring ×1
tree ×1
where ×1