【发布时间】:2018-01-15 19:30:40
【问题描述】:
我有一个包含几百万行的表,其中的行经常被插入,甚至更频繁地被提取。
行插入的时间并不重要,但提取的时间是因为它服务于一个网站。所以,我created already an index, that helped to fetch much faster。
查询非常简单,不包含JOINs。
SELECT 查询会出现问题。一旦用户执行了搜索,相同的SELECT 查询将每隔几秒运行一次以检查新行或更新行。但是,SELECT 查询第一次运行 50 秒,之后运行不到 1 秒,这并不奇怪。
这让我觉得问题不在于SELECT 语句本身,而在于其他问题。
表格是:
CREATE TABLE all_legs (
carrier TEXT,
dep_hub TEXT,
arr_hub TEXT,
dep_dt TIMESTAMP WITH TIME ZONE,
arr_dt TIMESTAMP WITH TIME ZONE,
price_ct INTEGER,
... 5 more cols ...,
PRIMARY KEY (carrier, dep_hub, arr_hub, dep_dt, arr_dt, ...3 other cols...)
)
索引是:
CREATE INDEX IF NOT EXISTS fetch_index ON all_legs(dep_dt, LEFT(dep_hub::text, 6), LEFT(arr_hub::text, 6));
选择查询:
SELECT * FROM all_legs
WHERE dep_dt >= %s
AND dep_dt < %s
AND (LEFT(dep_hub::text, 6) = %s AND LEFT(arr_hub::text, 6) = %s)
这种情况并不总是发生,因此难以复制。这里有一条来自我本地数据库的EXPLAIN 语句,它的数据比 Heroku 上的少,而且运行速度实际上相当快:
Index Scan using tz_idx on all_legs (cost=0.41..111184.33 rows=1 width=695) (actual time=128.100..136.690 rows=20 loops=1)
Index Cond: (("left"(dep_hub, 6) = 'ES-PMI'::text) AND ("left"(arr_hub, 6) = 'ES-MAD'::text))
Filter: ((dep_dt)::date = '2018-01-19'::date)
Rows Removed by Filter: 271
Planning time: 3.798 ms
Execution time: 138.525 ms
为什么第一次要慢得多,如何减少第一次查询的运行时间?
【问题讨论】:
-
我的意思是,我将多次运行同一个查询,因为我正在检查是否有新的或更新的行。所以我第一次运行新查询需要很长时间,以下时间都可以。我更新了问题以澄清它。
-
谁投票赞成关闭,如果你能解释为什么......
-
第一次运行查询需要更长的时间是很常见的。最常见的原因是表或索引中必要的数据块没有缓存在内存中(在 Linux 缓存或 pg 共享缓冲区中),必须首先从磁盘读取。当您重复查询时,大部分数据块已经被缓存,因此磁盘 IO 非常小或没有。
-
carrier TEXT, dep_hub TEXT, arr_hub TEXT,为什么这些PK列都是文本字段?他们的节奏是什么?您能否将它们挤出到单独的表中并通过代理键引用这些表? -
为了使第一次查询更快,需要在启动时填充缓存。您可以通过简单地对表运行虚拟查询或使用pgprewarm 扩展来做到这一点
标签: sql postgresql postgresql-performance