cha*_*shi 2 postgresql performance performance-tuning
我需要搜索一个非常大的PostgreSQL表(500+M行),我想限制返回的搜索结果,但是使用“limit”关键字并不能阻止对整组数据的搜索(正确吗?)
想象一下我的搜索结果包含 1M 行,但我只需要搜索结果中的前 100 条记录!PostgreSQL 数据库是否必须在内存中临时创建这 1M 搜索结果行,然后给我所需的 100 个结果?
或者有什么办法告诉PostgreSQL一旦找到100条记录就停止搜索?
这是我的表,当然还没有填充 500M 记录!
CREATE TABLE con
(
id bigserial NOT NULL,
tag1 integer NOT NULL DEFAULT 0,
tag2 integer NOT NULL DEFAULT 0,
ref1 integer NOT NULL DEFAULT 0,
ref2 integer NOT NULL DEFAULT 0,
CONSTRAINT con_pkey PRIMARY KEY (id)
)
Run Code Online (Sandbox Code Playgroud)
以及测试查询的解释分析:
explain analyze SELECT * FROM con where tag1 = '64813' and tag2 = '80'
Run Code Online (Sandbox Code Playgroud)
Seq Scan on con (cost=0.00..3215204.72 rows=2470 width=112) (actual time=0.016..36970.528 rows=7505 loops=1)
Filter: ((tag1 = 64813) AND (tag2 = 80))
Rows Removed by Filter: 152519685
Total runtime: 36972.921 ms
Run Code Online (Sandbox Code Playgroud)
但使用“limit”关键字并不能阻止对整组数据的搜索(正确吗?)
正确的; 它只会限制返回的结果数量。
对于某些类型的查询,它还可以限制首先扫描的数量,但在一般情况下您不能依赖它。
PostgreSQL 数据库是否必须在内存中临时创建这 1M 搜索结果行,然后给我所需的 100 个结果?
创建,是的。记忆中,不一定。它通常会溢出到磁盘,或者丢弃不需要的结果,因此它只保留前 100 个。这取决于查询的详细信息。
或者有什么办法告诉PostgreSQL一旦找到100条记录就停止搜索?
在可能的情况下编写一个查询。您尚未显示查询或架构,因此这部分无法有效回答。
一般来说,如果您有ORDER BY
某种搜索相关字段,则必须搜索整个数据集,然后过滤前 n 个结果。
简而言之:“这取决于”。具体来说,它取决于架构、可用索引以及您正在搜索的内容以及您想要的结果。
这:
SELECT id
FROM mytable
WHERE somefield > 100
ORDER BY somefield DESC
LIMIT 100;
Run Code Online (Sandbox Code Playgroud)
如果 上有索引,则只会扫描所需的行mytable(somefield DESC)
。
这:
SELECT id, title
FROM mytable
WHERE title LIKE '%something%'
ORDER BY calculate_relevance(title, 'something')
LIMIT 100;
Run Code Online (Sandbox Code Playgroud)
总是会扫描整个表,这既是因为中缀文本模式匹配 ( LIKE '%blah%'
) 不能使用 b 树索引,也是因为您无法在采用文字参数的函数上创建表达式索引(如虚函数的情况calculate_relevance
)多于。
所以...这完全取决于您正在寻找什么以及如何寻找。
这个答案对你来说是否过于笼统和笼统?所以问题来了。提供具体信息,您将得到更具体的答案。对于此类事情来说,包含示例数据的模式的 http://sqlfiddle.com/ 加上您的 PostgreSQL 版本、预期结果表以及您想要查找的内容的描述通常是最少的。
更新:这里有一些问题。
tag1
和/或上没有索引,tag2
因此 Pg 必须对表进行 seqscan,搜索它直到找到 100 个结果。这是极其低效的。
没有ORDER BY
,因此 PostgreSQL 可以返回 a 的任何结果LIMIT
,并以任何顺序返回它们。
您的架构显示出不必要的非规范化迹象。tag1
、tag2
等通常表明表格设计不佳。我强烈建议您学习关系数据库设计和规范化。
在这种特定情况下,如果您这样做,您将能够避免全表扫描CREATE INDEX con_tag1_tag2_idx ON con(tag1, tag2)
。但这仅适用于使用tag1
和 可选的搜索tag2
。它对于搜索 just 、 search for等没有多大帮助tag2
ref1
。(感谢 Erwin 关于多列索引使用的重要说明,其中不包括第一列,这对我来说是一个惊喜)。
不要创建大量索引。每个都使用磁盘空间并需要磁盘 I/O 来插入、更新和删除。
答案通常是适当的标准化。
总的来说,我认为你需要购买/借一些关于关系数据库设计和基础到中级 SQL 的优秀入门书籍,最好以 PostgreSQL 为重点,并进行一些研究。
归档时间: |
|
查看次数: |
2787 次 |
最近记录: |