我需要在一个包含大约 6 亿行的现有表上插入一个新的两字段索引。该表包含大约一年内积累的数据,每天大约添加 200 万行新行。
\n\n我知道一次性向一个非常大的表添加新索引需要很长时间,因此为了节省时间,我首先使用以下命令仅对最后几天的数据建立索引\xe2\x80\xa6
\n\nCREATE INDEX idx_001\nON message (deviceNumber, messageTime)\nWHERE messageTime >='07-May-2018 00:00:00' ;\nRun Code Online (Sandbox Code Playgroud)\n\n一天索引大约需要 3 小时,即大约 40 分钟。
\n\n理想情况下,我\xe2\x80\x99d 喜欢对整个表建立索引,但如果一天的数据需要 40 分钟,一次性完成将需要一周以上的时间。
\n\n我想我可以创建很多小索引,每个索引用于几天的数据,也许像这样\xe2\x80\xa6
\n\nCREATE INDEX idx_002\nON message (deviceNumber, messageTime)\nWHERE messageTime <'07-May-2018 00:00:00' AND messageTime >='01-May-2018 00:00:00' ;\nRun Code Online (Sandbox Code Playgroud)\n\n但我\xe2\x80\x99d 更喜欢坚持使用一个索引。有没有办法改变现有索引的 where 子句来增加覆盖天数?或者我必须创建很多小索引吗?
\n我想做这样的事情:
SELECT *
FROM information_schema.tables
WHERE table_schema IN (search_path)
Run Code Online (Sandbox Code Playgroud)
我在文档中找不到任何内容。是否可以?如何?
这是我的表数据:
对应的sqlfiddle - http://sqlfiddle.com/#!17/e3f09
create table jsonData (
id serial primary key,
data jsonb
);
insert into jsonData (data) values (
$${
"b": 2,
"c": [
{
"d": {
"e": true
}
},
{
"d": {
"e": true
}
},
{
"d": {
"e": true,
"f": "I'm here"
}
}
]
}
$$::jsonb),
(
$${
"a": 1,
"c": [
{
"d": {
"e": true
}
},
{
"d": {
"e": true
}
},
{
"d": {
"e": true
}
} …Run Code Online (Sandbox Code Playgroud) 我想尝试正则表达式匹配,null如果失败则返回。
以下查询尝试查找字符串中的第一个数字。结果会忽略带有 text 的条目'blah'。我更希望它返回一个null值。
这个问题可能与正则表达式无关,更多地与集合代数有关。我的预感是,有一种优雅的方法可以做到这一点,而不需要left join任何东西,尽管谷歌搜索被证明是徒劳的。
with test_data as (
select 'abc 123' as txt
union
select 'abc 456' as txt
union
select 'blah' as txt
)
select
txt,
(regexp_matches(txt, '\d+'))[1] as first_num
from
test_data
Run Code Online (Sandbox Code Playgroud) postgresql pattern-matching functions set-returning-functions regex
我使用 pg_restore 从目录备份恢复 50 GB 数据库,使用以下命令,该命令使用了 4 个作业:
pg_restore -d analytics -U postgres -j 4 -v "D:\Program Files\PostgreSQL\10\backups\Analytics_08_2018__7_53_21.36.compressed"
Run Code Online (Sandbox Code Playgroud)
我从命令行运行了这个。恢复时间比非并行恢复长约 2 小时。它似乎在恢复作业结束时继续创建索引
pg_restore: launching item 2817 INDEX nidx_bigrams_inc_hits
pg_restore: creating INDEX "public.nidx_bigrams_inc_hits"
pg_restore: finished item 2965 TABLE DATA trigrams
pg_restore: launching item 2822 INDEX nidx_trigrams_inc_hits
pg_restore: creating INDEX "public.nidx_trigrams_inc_hits"
pg_restore: finished item 2823 INDEX nidx_unigrams_inc_hits
pg_restore: finished item 2822 INDEX nidx_trigrams_inc_hits
pg_restore: finished item 2817 INDEX nidx_bigrams_inc_hits
pg_restore: finished main parallel loop
Run Code Online (Sandbox Code Playgroud)
每个 pg_restore“创建索引”作业在 pg_stat_activity 中的状态均为“空闲”。另一个 pg_restore 作业在提交时“空闲”。
我希望并行恢复能够比默认恢复快得多,而且它似乎一直在这样做,直到大约 …
我熟悉如何聚合行,如这个答案所示:
我还熟悉如何使用 HAVING 子句过滤聚合结果。
我似乎无法理解(因此它会粘住)是如何根据值或比较其他行来过滤行,而不聚合它们。
我知道答案涉及一些有关窗口函数或窗口子句的内容,事实上我以前已经成功完成过。但我似乎并没有记住它是如何运作的;我觉得我错过了一些基本的东西。
举个例子,信息如下:
fruit_name | some_field
------------+------------
apple | 3.25
apple | 6.8
apple | 0.7
orange | 2.6
banana | 3.5
banana | 2.49
cherry | 1
grapefruit | 2.6
grapefruit | 2.7
Run Code Online (Sandbox Code Playgroud)
我想要获取行数(按水果名称)大于 1 的所有行,因此它应该如下所示:
fruit_name | some_field
------------+------------
apple | 3.25
apple | 6.8
apple | 0.7
banana | 3.5
banana | 2.49
grapefruit | 2.6
grapefruit | 2.7
Run Code Online (Sandbox Code Playgroud)
执行此操作的正确惯用方法是什么?
(如果可能的话,我想要一个 SQL 标准答案,如果有一种更简单的 Postgres 特定方法来做到这一点,我也想知道。)
我想根据 ID 获取最多 100 行。id 是表的主键。
我编写的查询如下所示:
select * from table where id = any ($1);
Run Code Online (Sandbox Code Playgroud)
其中$1被插值为 ids 数组。
使用时EXPLAIN ANALYZE我得到以下计划(解释链接):
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------------------------
Limit (cost=0.43..44.98 rows=17 width=553) (actual time=100.048..834.209 rows=17 loops=1)
-> Index Scan using instagram_id_index_1000 on profiles_1000 (cost=0.43..44.98 rows=17 width=553) (actual time=100.046..834.163 rows=17 loops=1)
Index Cond: (id = ANY ('{34491540,28977916,33241270,33609141,31043380,29364420,30247037,33311491,36267571,32886281,32366574,32569254,33038689,31089076,29416100,30455309,31570597}'::integer[]))
Planning time: 424.512 ms
Execution time: 834.280 ms
(5 rows)
Run Code Online (Sandbox Code Playgroud)
当我实际执行它时(使用\timing),我得到的结果在 2-5 秒范围内!我真的无法接受如此糟糕的表现。EXPLAIN ANALYZE首先提供的执行时间就已经很长了。
一些上下文:
1)数据库是本地的,所以没有网络延迟
2)我查询的表是物化视图
3)我也尝试了 …
为了便于论证,我有一个简单的表格。我有一个选择 ids 并循环它们的函数,称为loop_test. 我可以选择一个 id 数组并循环它们,从而导致我在事务中进行更改。
CREATE OR REPLACE FUNCTION loop_test() RETURNS void AS $$
DECLARE
_ids_array INTEGER[];
_id INTEGER;
BEGIN
SELECT ARRAY(SELECT id FROM loop_test) INTO _ids_array;
FOREACH _id IN ARRAY _ids_array
LOOP
UPDATE loop_test SET looped = TRUE WHERE id = _id;
END LOOP;
END;
$$ LANGUAGE plpgsql;
Run Code Online (Sandbox Code Playgroud)
桌子:
db=# \d loop_test;
Table "public.loop_test"
Column | Type | Modifiers
---------------+---------+-----------
id | integer |
other_id | integer |
id_copy | integer |
other_id_copy | integer | …Run Code Online (Sandbox Code Playgroud) 我正在尝试将字符串模式与数组中的任何字符串进行匹配:
SELECT 'abc' LIKE ANY('{"abc","def"}') -- TRUE
-- BUT
SELECT 'ab%' LIKE ANY('{"abc","def"}') -- FALSE, I expect TRUE
Run Code Online (Sandbox Code Playgroud)
第二个查询有什么问题?
我想创建一个“不可变”的Postgres数据库,用户只能insert/ select(写入/读取)数据,但不能update/ delete(更改/删除)。
我知道有FOR UPDATE锁,但不知道如何使用它。
假设我有下表,如何使其不可变(或者,如果我理解正确,如何FOR UPDATE永久使用锁)?
CREATE TABLE account(
user_id serial PRIMARY KEY,
username VARCHAR (50) UNIQUE NOT NULL,
password VARCHAR (50) NOT NULL,
email VARCHAR (355) UNIQUE NOT NULL,
created_on TIMESTAMP NOT NULL,
last_login TIMESTAMP
);
Run Code Online (Sandbox Code Playgroud) postgresql ×10
performance ×2
aggregate ×1
array ×1
functions ×1
index ×1
parallelism ×1
permissions ×1
pg-restore ×1
regex ×1
select ×1