【发布时间】:2009-03-25 15:43:21
【问题描述】:
假设我有一个包含大量行的表,并且我想要索引的列之一可以有 20 个值之一。 如果我在列上放一个索引,它会很大吗?
如果是这样,为什么?如果我将数据分成 20 个表,每个表对应一个列的值,那么索引大小将是微不足道的,但索引效果是一样的。
【问题讨论】:
-
索引效果是一样的,但是当你想要第二个索引时呢?
标签: sql indexing partitioning
假设我有一个包含大量行的表,并且我想要索引的列之一可以有 20 个值之一。 如果我在列上放一个索引,它会很大吗?
如果是这样,为什么?如果我将数据分成 20 个表,每个表对应一个列的值,那么索引大小将是微不足道的,但索引效果是一样的。
【问题讨论】:
标签: sql indexing partitioning
糟糕的不是索引。它会将索引放在错误的列上,这会很糟糕。
说真的,你为什么需要一个单列的表?该数据的含义是什么?它有什么用途?
还有 20 张桌子?我建议你先阅读database design,或者向我们解释你的问题的背景。
【讨论】:
索引(或索引)并不糟糕。在过去的几十年中,许多非常聪明的人花费了大量时间来确保这一点。
但是,您的架构缺乏相同的专业知识和努力,可能确实很糟糕。
在所描述的情况下,分区相当于应用聚集索引。如果表以其他方式排序(或以任意顺序),则索引必须占用更多空间。根据平台的不同,非聚集索引的大小可能会随着行相对于索引值的排序程度的增加而减小。
YMMV.
【讨论】:
简短的回答: 索引是否糟糕:是和否
更长的答案: 如果使用得当,它们不会很烂。也许您应该开始阅读索引是如何工作的、为什么它们可以工作以及为什么它们有时不工作。
【讨论】:
没有索引不会很糟糕,但您必须注意如何使用它们,否则它们可能会适得其反。
第一:架构/设计
为什么要创建一个只有一列的表?这可能使规范化迈出了一大步。数据库设计是优化性能时要考虑的最重要的事情之一
第二:索引
简而言之,索引将帮助数据库对您的记录执行二进制搜索。如果没有对列(或一组列)的索引,数据库通常会退回到表扫描。表扫描非常昂贵,因为它涉及枚举每条记录。
对于索引扫描,数据库表中有多少记录并不重要。由于(平衡)二叉树搜索,记录数量翻倍只会导致一个额外的搜索步骤。
确定表的主键,SQL 会自动在该列上放置一个聚集索引。聚集索引执行得非常好。此外,您可以在 SELECT、JOIN、WHERE、GROUP BY 和 ORDER BY 语句中经常使用的列上放置非聚集索引。请记住索引有一定的重叠,尽量不要将聚集索引包含到非聚集索引中。
索引上的填充因子可能也很有趣。您是要针对读取(高填充因子 - 更少存储,更少 IO)或写入(低填充因子更多存储,更少重建数据库页面)优化您的表。
第三:分区
使用分区的原因之一是优化您的数据访问。假设您有 100 万条记录,其中 500,000 条记录不再相关,而是出于归档目的而存储。在这种情况下,您可以决定对表进行分区并将 500,000 条旧记录存储在慢速存储上,将其他 500,000 条记录存储在快速存储上。
衡量就是了解
了解发生了什么的最好方法是测量你的 cpu 和 io 发生了什么。 Microsoft SQL Server 有一些工具,例如 Management Studio 中的 Profiler 和执行计划,它们会告诉您查询的持续时间、读/写次数和 CPU 使用率。执行计划还将告诉您正在使用哪些或 IF 索引。令您惊讶的是,您可能会看到表扫描,尽管您没有预料到。
【讨论】:
假设我有一个包含大量行的表,我想要索引的一列可以有 20 个值之一。如果我在列上放一个索引,它会很大吗?
索引大小将与您的行数和索引值的长度成正比。
索引不仅保留索引值,还保留某种指向行的指针(Oracle 中的ROWID,PostgreSQL 中的LCID,InnoDB 中的主键等)。
如果您有 10,000 行和 1 个不同的值,您的索引中仍然会有 10,000 记录。
如果是这样,为什么?如果我将数据分成 20 个表,每个表对应一个列的值,则索引大小将是微不足道的,但索引效果将是相同的
在这种情况下,您将获得 20 个索引,其大小与原始索引的大小相同。
事实上,这种技术有时用于所谓的分区索引。它有它的优点和缺点。
【讨论】:
标准 b-tree 索引最适合具有选择性的索引,而本示例并非如此。你没有说你正在使用什么 DBMS; Oracle 有另一种类型的索引,称为位图索引,它更适合 OLAP 环境中的低选择性索引(因为这些索引维护成本高,不适合 OLTP 环境)。
优化器将根据统计数据决定是否认为索引有助于在最快的时间内获取数据;如果没有,优化器将不会使用它。
分区是另一种策略。在 Oracle 中,您可以将表定义为在一组列上进行分区,并且优化器可以按照您的建议自动执行“分区消除”。
【讨论】:
抱歉,我不太清楚你所说的“大”是什么意思。
如果您的索引是聚集索引,则每条记录的所有数据都将位于同一叶页上,因此只要您正确编写查询,就可以为您的表创建最有效的索引。
如果您的索引是非集群的,那么只有与索引相关的数据会出现在您的叶页上。然后,根据你有多少其他索引,再加上填充因子等细节,你的索引可能有效,也可能无效。一般来说,如果你的表上没有大量索引,你应该是安全的。
索引的效率还取决于您所说的进入列的 20 个值的数据类型。如果这些是预定义的值,那么它们的详细信息可能应该在具有简单主键数据类型(如 Int/Number)的查找表中。然后将该列作为外键添加到您的表中,并在该列上添加索引。
最终,您可以在列上拥有一个完美的索引。但它的最佳用途将在很大程度上取决于您编写的查询。因此,如果您的查询使用了索引,那么您就是黄金。
【讨论】:
索引纯粹是为了性能。如果索引不能提高您感兴趣的查询的性能,那么它就很糟糕。
至于磁盘使用情况,您必须权衡您的顾虑。不同的 SQL 提供程序构建索引的方式不同,但作为客户端,您通常相信他们会尽力而为。在您所描述的情况下,聚集索引可能在大小和性能方面都是最佳的。
【讨论】:
它足够大,可以按排序顺序保存所有行的这些值。
假设您有 20 个不同的 4 个字符的字符串和 100 万行,那么保存这些值至少需要 400 万字节(如果 16 位 unicode 则为 8 个字节)。
【讨论】: