数据库中的分区和索引有什么区别? (性能方面)
What is the difference between partitioning and indexing in DB ? (Performance-Wise)
我是 SQL 的新手,一直在尝试优化我的微服务对我的数据库 (Oracle SQL) 的查询性能。
根据我的研究,我检查过您可以执行 indexing 和 partitioning 来提高查询性能,我似乎都知道的概念以及如何去做,但我不确定两者之间的区别?
例如,假设我有 table Orders,其中有 1 亿个条目
列数:
- OrderId (PK)
- CustomerId(6 位唯一编号)
- 订单(订单是什么。例如:“汉堡”)
- CreatedTime(时间戳)
本质上,这两种方法都“细分”了 orders table 这样数据库查询就不需要扫描数据库中的所有 1 亿个条目,对吗?
假设我想查找“2020-01-30”的订单,我可以在 createdTime 上创建索引以提高性能。
但是我也可以根据 createdTime 创建一个分区来提高性能。 (分区是每天)
在这种情况下,这两种方法有什么区别吗?一个比另一个好吗?
有几种分区方式 - 按范围、按列表、按散列和按引用(尽管这种方式并不常见)。
如果您要按日期列进行分区,通常会使用一个范围,因此一个 month/week/day 使用一个分区,另一个使用另一个分区,依此类推。如果您想过滤此日期相等的行到一个值,那么您可以进行分区完整 table 扫描,以通过完整扫描读取包含此数据的所有分区。如果分区中的大部分数据都与您的过滤器相匹配,这最终可能会非常有效 - 应用相同的思考来考虑完整的 table 扫描通常是否是一个好主意,但是当 table 已经过滤掉了。如果您想查找一小时长的日期范围,并且按月为间隔按范围进行分区,那么您将读取比必要数据多 730 倍的数据。本地索引在这种情况下很有用。
较小的分区也有助于解决这个问题,但您最终可能会遇到拥有数千个分区的情况。如果您有不知道需要读取哪个分区的选择性查询——您可能需要全局索引。这些为所有分区维护操作增加了很多工作量。
如果改为索引日期列,则可以快速确定 table 中符合过滤器的行的位置。这在索引中很容易,因为它只是一个排序列表——您在索引中找到与过滤器匹配的第一个键并读取直到它不再匹配。然后您必须使用单块读取来查找这些行。索引的一般效率规则适用 - 您需要使用过滤器读取的数据越少,索引就越有用。
通常,查询不仅仅包含日期过滤器。这些额外的过滤器可能更适合您的分区方案。您也可以只在索引中包含列(记住索引的黄金法则会告诉您,如果您使用的列带有相等过滤器,它应该位于索引中使用范围过滤器的列之前)。
您通常只需建立索引即可获得所需的所有性能。当您有需要读取大量数据的重要查询(通常是报告查询)或需要执行诸如清除 X 个月之前的数据之类的操作时,分区真正发挥作用。
我是 SQL 的新手,一直在尝试优化我的微服务对我的数据库 (Oracle SQL) 的查询性能。
根据我的研究,我检查过您可以执行 indexing 和 partitioning 来提高查询性能,我似乎都知道的概念以及如何去做,但我不确定两者之间的区别?
例如,假设我有 table Orders,其中有 1 亿个条目 列数:
- OrderId (PK)
- CustomerId(6 位唯一编号)
- 订单(订单是什么。例如:“汉堡”)
- CreatedTime(时间戳)
本质上,这两种方法都“细分”了 orders table 这样数据库查询就不需要扫描数据库中的所有 1 亿个条目,对吗?
假设我想查找“2020-01-30”的订单,我可以在 createdTime 上创建索引以提高性能。 但是我也可以根据 createdTime 创建一个分区来提高性能。 (分区是每天)
在这种情况下,这两种方法有什么区别吗?一个比另一个好吗?
有几种分区方式 - 按范围、按列表、按散列和按引用(尽管这种方式并不常见)。
如果您要按日期列进行分区,通常会使用一个范围,因此一个 month/week/day 使用一个分区,另一个使用另一个分区,依此类推。如果您想过滤此日期相等的行到一个值,那么您可以进行分区完整 table 扫描,以通过完整扫描读取包含此数据的所有分区。如果分区中的大部分数据都与您的过滤器相匹配,这最终可能会非常有效 - 应用相同的思考来考虑完整的 table 扫描通常是否是一个好主意,但是当 table 已经过滤掉了。如果您想查找一小时长的日期范围,并且按月为间隔按范围进行分区,那么您将读取比必要数据多 730 倍的数据。本地索引在这种情况下很有用。
较小的分区也有助于解决这个问题,但您最终可能会遇到拥有数千个分区的情况。如果您有不知道需要读取哪个分区的选择性查询——您可能需要全局索引。这些为所有分区维护操作增加了很多工作量。
如果改为索引日期列,则可以快速确定 table 中符合过滤器的行的位置。这在索引中很容易,因为它只是一个排序列表——您在索引中找到与过滤器匹配的第一个键并读取直到它不再匹配。然后您必须使用单块读取来查找这些行。索引的一般效率规则适用 - 您需要使用过滤器读取的数据越少,索引就越有用。
通常,查询不仅仅包含日期过滤器。这些额外的过滤器可能更适合您的分区方案。您也可以只在索引中包含列(记住索引的黄金法则会告诉您,如果您使用的列带有相等过滤器,它应该位于索引中使用范围过滤器的列之前)。
您通常只需建立索引即可获得所需的所有性能。当您有需要读取大量数据的重要查询(通常是报告查询)或需要执行诸如清除 X 个月之前的数据之类的操作时,分区真正发挥作用。