alf*_*onx 7 postgresql performance index query-performance
我使用 PostgreSQL 9.2。我有一个大约有 500 万行和 150 列的表。该表根本没有变化(我每年更换一次)。用户在任何某些列上使用各种过滤器查询此表,例如
select * from table where C > 43 and H is not null;
select * from table where A is null and F < 10 and F > 1 and X > 2;
Run Code Online (Sandbox Code Playgroud)
为了提高性能,我计划在表的每一列上创建一个索引。心里有些感慨,先问问各位高手:上面描述的用例,在每一列上都创建一个索引,这样设计好不好?
更新:我必须推测真实的用例。我还不能衡量确切的查询。这是在设计阶段。
服务器配备了良好的RAM和SSD存储,所以现在查询已经“快速”了,当我依次触发类似查询时,我可以感受到缓存的效果。
列的类型为 double、integer、timestamp 和 geometry(显式获取“gist”索引)。
查询将包括 1 到 10 列。通常~6。结果通常小于 20k 行。对一列的查询永远不会与另一列相关。
感谢所有的解释。我将做什么: * 选择我认为最常用的列的 1/4 并创建索引。* 等待更多的测试/使用,然后开始测量/分析查询和用例。
谢谢
当您说“为了性能”时,您采取的是狭隘的观点——“性能”SELECT仅指性能,一次一个查询,不考虑缓存和 I/O 争用问题。
是的,每列都有一个索引可能会提高读取性能。它肯定会降低写入性能(INSERT,UPDATE和DELETE),尽管这对您的数据库来说不是问题。更微妙的是,更多的索引意味着更多的 RAM 空间争用来缓存索引,这意味着对任何给定索引的扫描将导致磁盘读取速度变慢的可能性更大。
还有一个事实是,您可以索引的不仅仅是单个列。创建多列、部分、表达式和/或降序索引以最好地满足您的查询需求通常是最有效的。您根本无法创建所有可能的索引。这是一个最近的真实世界索引示例,如果不分析需要它的查询,您就永远不会创建:
CREATE INDEX contfloattable_tag_and_timeseg
ON contfloattable(tagindex, (floor(extract(epoch FROM dateandtime) / 60 / 15) ));
Run Code Online (Sandbox Code Playgroud)
所以:你可以在每一列上创建一个索引,但这是一个坏主意。使用EXPLAINAND EXPLAIN ANALYZE(可能通过auto_explain模块)来分析您的工作负载和查询,并根据您实际查询表的方式做出索引决策。你不使用的索引在读/写环境中会伤害你,而在只读环境中不会有任何好处。
不要孤立地查看查询。看图案。如果 query1 似乎想要一个索引,col1而 query2 似乎想要一个col1和的索引col2,不要费心只在 上创建索引col1。在 上创建复合索引col1, col2;它几乎与col1单独搜索一样快,并且比维护两个索引并让它们争夺缓存空间和磁盘 I/O 更好。
顺便说一句,这听起来更像是OLAP工作负载而不是OLTP工作负载,因此您可能需要考虑为 OLAP 工作负载设计的模式,例如带有事实和维度表的星型模式。
答案是(几乎总是)不。
您创建的每个索引都意味着使用更多的磁盘空间、更长的维护窗口以及更高的成本,如果永远不应该更改的表(除了每年更换一次)确实发生了更改。它们增加了备份的大小,并使适应灾难恢复窗口变得更加困难。此外,其中许多索引可能永远不会被使用,因此它们只是无用功。
然后,您必须考虑多列索引。在您的两个示例中,您都有两列。如果您只索引单个列,则没有单个非聚集索引可能足够好,因此查询将返回到聚集索引。然后是三列索引、四列索引等等。
更好的办法是确定哪些查询是常见的,并开始索引它们。我对 postgresql 内部结构不太熟悉,但是有一些链接可以帮助设置统计信息收集。一旦您对用户实际使用的查询有了相当明确的了解,您就可以创建有用的索引。即便如此,这也不是一个完美的策略:你(比喻地)在人们行走的地方建造道路,但创造这些道路的人必须艰难地穿过它,直到你能找到他们要去的地方并建造道路帮助。这是一个反动的过程,但它可能会捕获相当大比例的常见用途。
但是,由于这是一个只读数据库,因此可以合理安全地创建适合大部分用户请求的公共数据子集(通过单独的表或创建物化视图)。您还可以使用比典型 OLTP 表更多的非聚集索引。索引肯定有边际成本,但是当您不需要过多担心插入、更新和删除时,它们会更低。如果围绕日期或其他一些类似字段构建了大量查询,您可能会在该列上对表进行分区。
| 归档时间: |
|
| 查看次数: |
3403 次 |
| 最近记录: |