- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个包含大约 2 亿行的 datavalue
表,在 site_id
和 paramter_id
上都有索引。我需要执行诸如“返回所有带数据的站点”和“返回带数据的所有参数”之类的查询。 site
表只有200行左右,parameter
表也只有100行左右。
site
查询很快并且使用索引:
EXPLAIN ANALYZE
select *
from site
where exists (
select 1 from datavalue
where datavalue.site_id = site.id limit 1
);
Seq Scan on site (cost=0.00..64.47 rows=64 width=113) (actual time=0.046..1.106 rows=89 loops=1)
Filter: (SubPlan 1)
Rows Removed by Filter: 39
SubPlan 1
-> Limit (cost=0.44..0.47 rows=1 width=0) (actual time=0.008..0.008 rows=1 loops=128)
-> Index Only Scan using ix_datavalue_site_id on datavalue (cost=0.44..8142.71 rows=248930 width=0) (actual time=0.008..0.008 rows=1 loops=128)
Index Cond: (site_id = site.id)
Heap Fetches: 0
Planning time: 0.361 ms
Execution time: 1.149 ms
相同的参数查询相当慢并且不使用索引:
EXPLAIN ANALYZE
select *
from parameter
where exists (
select 1 from datavalue
where datavalue.parameter_id = parameter.id limit 1
);
Seq Scan on parameter (cost=0.00..20.50 rows=15 width=2648) (actual time=2895.972..21331.701 rows=15 loops=1)
Filter: (SubPlan 1)
Rows Removed by Filter: 6
SubPlan 1
-> Limit (cost=0.00..0.34 rows=1 width=0) (actual time=1015.790..1015.790 rows=1 loops=21)
-> Seq Scan on datavalue (cost=0.00..502127.10 rows=1476987 width=0) (actual time=1015.786..1015.786 rows=1 loops=21)
Filter: (parameter_id = parameter.id)
Rows Removed by Filter: 7739355
Planning time: 0.123 ms
Execution time: 21331.736 ms
这到底是怎么回事?或者,执行此操作的好方法是什么?
部分表格说明:
id BIGINT DEFAULT nextval('datavalue_id_seq'::regclass) NOT NULL,
value DOUBLE PRECISION NOT NULL,
site_id INTEGER NOT NULL,
parameter_id INTEGER NOT NULL,
deployment_id INTEGER,
instrument_id INTEGER,
invalid BOOLEAN,
Indexes:
"datavalue_pkey" PRIMARY KEY, btree (id)
"datavalue_datetime_utc_site_id_parameter_id_instrument_id_key" UNIQUE CONSTRAINT, btree (datetime_utc, site_id, parameter_id, instrument_id)
"ix_datavalue_instrument_id" btree (instrument_id)
"ix_datavalue_parameter_id" btree (parameter_id)
"ix_datavalue_site_id" btree (site_id)
"tmp_idx" btree (site_id, datetime_utc)
Foreign-key constraints:
"datavalue_instrument_id_fkey" FOREIGN KEY (instrument_id) REFERENCES instrument(id) ON UPDATE CASCADE ON DELETE CASCADE
"datavalue_parameter_id_fkey" FOREIGN KEY (parameter_id) REFERENCES parameter(id) ON UPDATE CASCADE ON DELETE CASCADE
"datavalue_site_id_fkey" FOREIGN KEY (site_id) REFERENCES coastal.site(id) ON UPDATE CASCADE ON DELETE CASCADE
"datavalue_statistic_type_id_fkey"
编辑:这是计数分布
select count(parameter_id), parameter_id from datavalue group by parameter_id
88169 14
2889171 8
15805 17
8570 12
4257262 21
3947049 15
1225902 2
4091090 3
103877 10
633764 11
994442 18
49232 20
14935 4
563638 13
2955919 7
最佳答案
更新:正如 a_horse_with_no_name 提到的,您可以删除 LIMIT 1,查询将使用索引。
显然 PostgreSQL 错误地假设如果您执行子查询它会触及整个数据库并忽略了 LIMIT 1。(事实证明这是不必要的。)
我在我的笔记本电脑上生成了相同的分布:
create table testtbl (id integer, par_id integer);
insert into testtbl (id, par_id) values (0,0 );
insert into testtbl (id, par_id) select "generate_series", 4 from generate_series((select max(id) from testtbl), (select max(id) from testtbl)+14935);
insert into testtbl (id, par_id) select "generate_series", 12 from generate_series((select max(id) from testtbl), (select max(id) from testtbl)+8570);
insert into testtbl (id, par_id) select "generate_series", 17 from generate_series((select max(id) from testtbl), (select max(id) from testtbl)+15805);
insert into testtbl (id, par_id) select "generate_series", 20 from generate_series((select max(id) from testtbl), (select max(id) from testtbl)+49232);
insert into testtbl (id, par_id) select "generate_series", 14 from generate_series((select max(id) from testtbl), (select max(id) from testtbl)+88169);
insert into testtbl (id, par_id) select "generate_series", 10 from generate_series((select max(id) from testtbl), (select max(id) from testtbl)+103877);
insert into testtbl (id, par_id) select "generate_series", 2 from generate_series((select max(id) from testtbl), (select max(id) from testtbl)+1225902);
insert into testtbl (id, par_id) select "generate_series", 8 from generate_series((select max(id) from testtbl), (select max(id) from testtbl)+2889171);
insert into testtbl (id, par_id) select "generate_series", 7 from generate_series((select max(id) from testtbl), (select max(id) from testtbl)+2955919);
insert into testtbl (id, par_id) select "generate_series", 3 from generate_series((select max(id) from testtbl), (select max(id) from testtbl)+4091090);
insert into testtbl (id, par_id) select "generate_series", 13 from generate_series((select max(id) from testtbl), (select max(id) from testtbl)+563638);
insert into testtbl (id, par_id) select "generate_series", 11 from generate_series((select max(id) from testtbl), (select max(id) from testtbl)+633764);
insert into testtbl (id, par_id) select "generate_series", 18 from generate_series((select max(id) from testtbl), (select max(id) from testtbl)+994442);
insert into testtbl (id, par_id) select "generate_series", 15 from generate_series((select max(id) from testtbl), (select max(id) from testtbl)+3947049);
insert into testtbl (id, par_id) select "generate_series", 21 from generate_series((select max(id) from testtbl), (select max(id) from testtbl)+4257262);
delete from testtbl where id = 0 and par_id = 0;
create index testtbl_paridx on testtbl (par_id);
create table parameter (id integer);
insert into parameter select * from generate_series (1, 28);
analyze testtbl;
然后如果我运行查询:
testdb=# explain analyze select * from parameter where exists (select 1 from testtbl where testtbl.par_id = parameter.id limit 1);
QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------------
Seq Scan on parameter (cost=0.00..643.29 rows=1200 width=4) (actual time=4083.514..54216.575 rows=15 loops=1)
Filter: (SubPlan 1)
Rows Removed by Filter: 13
SubPlan 1
-> Limit (cost=0.00..0.25 rows=1 width=0) (actual time=1936.299..1936.299 rows=1 loops=28)
-> Seq Scan on testtbl (cost=0.00..369619.35 rows=1455927 width=0) (actual time=1936.294..1936.294 rows=1 loops=28)
Filter: (par_id = parameter.id)
Rows Removed by Filter: 14870626
Planning time: 0.151 ms
Execution time: 54216.620 ms
(10 rows)
如果我禁用顺序扫描:
testdb=# set local enable_seqscan = off;
SET
testdb=# explain analyze select * from parameter where exists (select 1 from testtbl where testtbl.par_id = parameter.id limit 1);
QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------------------------------
Seq Scan on parameter (cost=10000000000.00..10000001395.02 rows=1200 width=4) (actual time=0.077..0.563 rows=15 loops=1)
Filter: (SubPlan 1)
Rows Removed by Filter: 13
SubPlan 1
-> Limit (cost=0.44..0.57 rows=1 width=0) (actual time=0.019..0.019 rows=1 loops=28)
-> Index Only Scan using ix_testtbl_par on testtbl (cost=0.44..188678.87 rows=1455927 width=0) (actual time=0.018..0.018 rows=1 loops=28)
Index Cond: (par_id = parameter.id)
Heap Fetches: 15
Planning time: 0.169 ms
Execution time: 0.605 ms
(10 rows)
速度快,但有点老套。你想使用 SET LOCAL , 为了不禁用所有查询的顺序扫描。 SET LOCAL 在事务提交之前一直有效。
更新:更好的选择是按照 a_horse_with_no_name 的建议完全删除 LIMIT 1。
testdb=# explain analyze select * from parameter where exists (select 1 from testtbl where testtbl.par_id = parameter.id );
QUERY PLAN
----------------------------------------------------------------------------------------------------------------------------------------------
Nested Loop Semi Join (cost=0.44..1591.08 rows=1200 width=4) (actual time=0.070..0.492 rows=15 loops=1)
-> Seq Scan on parameter (cost=0.00..34.00 rows=2400 width=4) (actual time=0.010..0.018 rows=28 loops=1)
-> Index Only Scan using testtbl_paridx on testtbl (cost=0.44..29379.76 rows=1455923 width=4) (actual time=0.016..0.016 rows=1 loops=28)
Index Cond: (par_id = parameter.id)
Heap Fetches: 15
Planning time: 0.216 ms
Execution time: 0.532 ms
(7 rows)
关于sql - 带有索引的 Postgres 奇怪行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35658238/
我想创建一个基于 jQuery 的非常简单的 html 编辑器(不是所见即所得)。 我的问题是如何制作 textarea或 div可能 在上面写一些文字 然后样式即标签(例如 some stuff 将
根据文档 isset 条款“测试此项目中是否已设置给定属性”。我不明白设置属性时 isset 返回 true 还是 false 在下面的代码片段中,当 env.JAVA_HOME 未设置时,java.
我正在尝试取消映射 o这是执行 :only 的默认命令( :help :only ),所以我尝试的第一件事是: nmap o 这种作品,除非我按 ,等待超过timeoutlen ms 然后按 o
我有以下型号: class MetaData(models.Model): created_at = models.DateTimeField(auto_now_add=True, auto_
下面列出了两行代码。两者对日期和时间的期望相同,但只有一个有效。我正在使用 R 3.1。 以下不起作用: DateTime2=strftime("08/13/2010 05:26:24.350", f
我有一个关于 C 代码的问题。 #include void foo(void){ int a; printf("%d\n",a); } void bar(void){
如果文件大小 > 8k,为什么读取的最后一个字节 = 0? private static final int GAP_SIZE = 8 * 1024; public static void main(
我有一个命令 Get-Testdata从不同来源检索测试数据并将这些数据存储到 PSObject以不同的值作为属性。然后将对象总数存储为数组,以便于操作、排序、计算等。 我的问题是我希望能够将这些数据
我正在使用 epoll 将大消息写入使用 HTTP 协议(protocol)的服务器。 fds 都设置为非阻塞,我正在使用边缘触发事件。我知道对于 EPOLLIN,我需要循环读取 fd,直到返回 EA
这对我来说听起来很奇怪: $test_1 = 'string'; $test_2 = '0'; var_dump(intval($test_1)); // Output: int 0 var_dump
这个问题在这里已经有了答案: Java: Integer equals vs. == (7 个回答) 7年前关闭。 请您解释以下行为。 public class EqAndRef { publ
Drupal 的行为到底是什么? 它为模块开发人员提供什么类型的服务层? 它映射到 jQuery.ready 的关系类型是什么? 最佳答案 长版:Drupal.behaviors 不仅仅是 jQuer
以下代码: dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ for (int i=0
人们可以将项目添加到数据库中。我让他们选择在此时添加它,或手动选择日期。 因此我得到了这个 HTML 结构。 (请注意,我将日期和时间选择器妥协为只有一行文本) Selec
创建了一个数据框: simpleDF is.na(simpleDF$vals) [1] TRUE TRUE FALSE > is.nan(simpleDF$vals) [1] FALSE TRU
我有一个大的 docker 镜像 A,我创建了一个新的 Dockerfile FROM A RUN rm /big-folder 我尝试使用以下方法构建图像: docker build --squas
我想知道以下情况下 JVM 的行为是什么: JVM 最小堆大小 = 500MB JVM 最大堆大小 = 2GB 操作系统有 1GB 内存 JVM启动后,程序运行一段时间后,使用内存超过1GB。我想知道
我们正在使用 spikeearrest 策略,但我们不了解其工作原理。峰值逮捕配置如下: 5pm 阅读文档,我们了解到,如果我们在一分钟内调用此流超过 5 次,则该策略将在第 5 次之后
我正在使用 cURL 发送 POST 请求: curl http://tarvos.local:8080/partial_Users/2 -d '{currentPage : 1, firstID :
我的表中有 6442670 条记录,我正在使用以下命令获取它们jdbctemplate 使用行号一次 1000000 个。以下是查询 select * from (select rowNum rn
我是一名优秀的程序员,十分优秀!