当前位置: 首页 > 知识库问答 >
问题:

当我们使用唯一索引而不是非唯一索引时,是否有任何性能增强?

谭玄天
2023-03-14

我知道如果数据是唯一的,理论上唯一索引会比非唯一索引快。

因为唯一索引能够提供更多信息,并让查询优化器选择更有效的执行计划。

我正在做一些测试,想证明唯一索引可能比执行计划中的非唯一索引更好,但结果显示它们是相同的。。。

CREATE TABLE T3(
    ID INT NOT NULL,
    val INT NOT NULL,
    col1 UUID NOT NULL,
    col2 UUID NOT NULL,
    col3 UUID NOT NULL,
    col4 UUID NOT NULL,
    col5 UUID NOT NULL,
    col6 UUID NOT NULL
);

CREATE INDEX IX_ID_T3 ON T3 (ID);
CREATE UNIQUE INDEX UIX_ID_T3 ON T3 (ID);

INSERT INTO T3
SELECT i,
       RANDOM() * 1000000,
       md5(random()::text || clock_timestamp()::text)::uuid,
       md5(random()::text || clock_timestamp()::text)::uuid,
       md5(random()::text || clock_timestamp()::text)::uuid,
       md5(random()::text || clock_timestamp()::text)::uuid,
       md5(random()::text || clock_timestamp()::text)::uuid,
       md5(random()::text || clock_timestamp()::text)::uuid
FROM generate_series(1,1000000) i;

vacuum ANALYZE T3;

我创建了一个表和两个索引(< code>IX_ID_T3不唯一,< code>UIX_ID_T3唯一),然后插入了1000000个样本行。

插入数据后,我运行< code >真空分析T3;

--drop index IX_ID_T3 

EXPLAIN (ANALYZE,TIMING ON,BUFFERS ON)
SELECT DISTINCT a1.ID
FROM T3 a1 INNER JOIN T3 a2
ON a1.id = a2.id
WHERE a1.id <= 300000

第一个查询,我试图通过Merge-JoinUIX_ID_T3IX_ID_T3之间进行测试

缓冲区:共享命中和执行计划没有区别。

这是我的行刑计划

-- UIX_ID_T3 
"Unique  (cost=0.85..41457.94 rows=298372 width=4) (actual time=0.030..267.207 rows=300000 loops=1)"
"  Buffers: shared hit=1646"
"  ->  Merge Join  (cost=0.85..40712.01 rows=298372 width=4) (actual time=0.030..200.412 rows=300000 loops=1)"
"        Merge Cond: (a1.id = a2.id)"
"        Buffers: shared hit=1646"
"        ->  Index Only Scan using uix_id_t3 on t3 a1  (cost=0.42..8501.93 rows=298372 width=4) (actual time=0.017..49.237 rows=300000 loops=1)"
"              Index Cond: (id <= 300000)"
"              Heap Fetches: 0"
"              Buffers: shared hit=823"
"        ->  Index Only Scan using uix_id_t3 on t3 a2  (cost=0.42..25980.42 rows=1000000 width=4) (actual time=0.010..40.170 rows=300000 loops=1)"
"              Heap Fetches: 0"
"              Buffers: shared hit=823"
"Planning Time: 0.171 ms"
"Execution Time: 282.919 ms"

---IX_ID_T3 
"Unique  (cost=0.85..41420.43 rows=297587 width=4) (actual time=0.027..230.256 rows=300000 loops=1)"
"  Buffers: shared hit=1646"
"  ->  Merge Join  (cost=0.85..40676.46 rows=297587 width=4) (actual time=0.027..173.308 rows=300000 loops=1)"
"        Merge Cond: (a1.id = a2.id)"
"        Buffers: shared hit=1646"
"        ->  Index Only Scan using ix_id_t3 on t3 a1  (cost=0.42..8476.20 rows=297587 width=4) (actual time=0.015..41.606 rows=300000 loops=1)"
"              Index Cond: (id <= 300000)"
"              Heap Fetches: 0"
"              Buffers: shared hit=823"
"        ->  Index Only Scan using ix_id_t3 on t3 a2  (cost=0.42..25980.42 rows=1000000 width=4) (actual time=0.009..34.019 rows=300000 loops=1)"
"              Heap Fetches: 0"
"              Buffers: shared hit=823"
"Planning Time: 0.195 ms"
"Execution Time: 243.711 ms"

还有另一个问题是-独特-索引-更好-为-列-搜索-性能-pgsql-mysql讨论这个主题。

我也尝试过测试问题查询的答案,但执行计划没有什么不同。

EXPLAIN (ANALYZE,TIMING ON,BUFFERS ON)
SELECT  id
FROM    T3
ORDER BY
        id
LIMIT 10;
-- using IX_ID_T3 
"Limit  (cost=0.42..0.68 rows=10 width=4) (actual time=0.034..0.036 rows=10 loops=1)"
"  Buffers: shared hit=4"
"  ->  Index Only Scan using uix_id_t3 on t3  (cost=0.42..25980.42 rows=1000000 width=4) (actual time=0.033..0.034 rows=10 loops=1)"
"        Heap Fetches: 0"
"        Buffers: shared hit=4"
"Planning Time: 0.052 ms"
"Execution Time: 0.047 ms"

-- using IX_ID_T3
"Limit  (cost=0.42..0.68 rows=10 width=4) (actual time=0.026..0.029 rows=10 loops=1)"
"  Buffers: shared hit=4"
"  ->  Index Only Scan using ix_id_t3 on t3  (cost=0.42..25980.42 rows=1000000 width=4) (actual time=0.025..0.027 rows=10 loops=1)"
"        Heap Fetches: 0"
"        Buffers: shared hit=4"
"Planning Time: 0.075 ms"
"Execution Time: 0.043 ms"

我看到了很多不同的文章,但我无法通过执行计划证明唯一索引比非唯一索引更好。

后唯一约束与索引

问题:

任何人都可以证明唯一索引可能比执行计划中的非唯一索引更好,并向我们展示查询和执行计划吗?

据我所知,sql-server的唯一索引不仅是一个约束,而且比非唯一索引有更好的性能。

合并连接的许多秘密

共有1个答案

上官联
2023-03-14

唯一索引的扫描速度不会比非唯一索引快。查询执行速度的唯一潜在好处可能是优化程序可以从唯一性中进行某些推断,例如删除不必要的联接。

唯一索引的主要用途是实现表约束,而不是提供优于非唯一索引的性能优势。

下面是一个例子:

CREATE TABLE parent (pid bigint PRIMARY KEY);

CREATE TABLE child (
   cid bigint PRIMARY KEY,
   pid bigint UNIQUE REFERENCES parent
);

EXPLAIN (COSTS OFF)
SELECT parent.pid FROM parent LEFT JOIN child USING (pid);

     QUERY PLAN     
════════════════════
 Seq Scan on parent
(1 row)

如果没有 child.pid 上的唯一约束(由唯一索引实现),则无法删除联接。

 类似资料:
  • 问题内容: 就性能而言,MySQL唯一索引和非唯一索引有什么区别? 假设我要在2列的组合上创建索引,并且该组合是唯一的,但是我创建了一个非唯一的索引。这会对MySQL使用的性能或内存产生重大影响吗? 同样的问题, 主 键和 唯一 索引之间有区别吗? 问题答案: UNIQUE和PRIMARY KEY是 约束 ,而不是索引。尽管大多数数据库通过使用索引来实现这些约束。除了索引之外,约束的额外开销也微不

  • 问题内容: 从pandas文档中,我收集到,唯一值索引使某些操作高效,并且偶尔可以容忍非唯一索引。 从外部看,看起来非唯一索引没有以任何方式被利用。例如,以下查询足够慢,以至于似乎正在扫描整个数据帧 (我意识到这两个查询不会返回相同的内容,这只是一个对非唯一索引的调用要慢得多的示例) 有什么办法哄骗大熊猫使用更快的查找方法,例如对非唯一索引和/或排序索引进行二进制搜索? 问题答案: 当索引是唯一的

  • 问题内容: 不知道在PostgreSQL 9.3+中是否可行,但是我想在非唯一列上创建唯一索引。对于像这样的表: 我想仅能[快速]查询不同的日子。我知道我可以用来帮助执行不同的搜索,但是如果不同值的数量大大少于索引覆盖的行数,这似乎会增加额外的开销。就我而言,大约30天中有1天与众不同。 我是创建关系表以仅跟踪唯一条目的唯一选择吗?思维: 并在每次插入数据时使用触发器来更新它。 问题答案: 索引只

  • 我正在学习Spring Data JPA和Spring Security以及用户角色,我想知道如何使用Spring Data JPA搜索非唯一索引。例如,我有3个MySQL表,这是联接表: 我想找到一个特定用户的所有角色。所以我想在user_role表中按user_id进行搜索,这不是唯一的键。 用户实体:

  • 以下两者之间有区别吗: 以及: 在这两种情况下,名称是否唯一?索引唯一时意味着什么? 编辑:Postgres是唯一的约束,而索引没有回答我的问题。它考虑了FK的情况。我的问题与FK无关。我只想知道在这个例子中,这两个操作是否等价,其中不涉及FK。