【问题标题】:Same SQL request, CockroachDB takes 4min SQL Server takes 35ms. Am I missing something?同样的 SQL 请求,CockroachDB 需要 4 分钟 SQL Server 需要 35 毫秒。我错过了什么吗?
【发布时间】:2020-08-22 00:22:19
【问题描述】:

The database 仅包含 2 个表:

  • 钱包(100 万行)
  • 事务(1500 万行)

CockroachDB 19.2.6 在 3 台 Ubuntu 机器上运行

  • 每个 2vCPU
  • 每个 8GB 内存
  • Docker 集群容器

SQL Server 2019 在一台机器上运行 Windows Server 2019

  • 4vCPU
  • 16GB 内存

这是请求

select * from transaction t 
join wallet s on t.sender_id=s.id
join wallet r on t.receiver_id=r.id
limit 10;
  • SQL Server 只需 35 毫秒即可返回前 10 个结果
  • CockroachDB 需要 3.5-5 分钟。

1) 我知道CockroachDB 的基础设施不够公平,但是.. 差异实在太大了。我错过了什么吗?还是 CockroachDB 对于这个特定的 SQL 请求非常慢?

2) 当我执行这个请求时,所有 3 个蟑螂节点的 CPU 都上升到了 100%。正常吗?

更新:这里是请求“解释”。我不知道如何阅读它..

> explain select * from transaction t
            -> join wallet s on t.sender_id=s.id
            -> join wallet r on t.receiver_id=r.id
            -> limit 10;
        tree         |       field        |     description
+---------------------+--------------------+----------------------+
                    | distributed        | true
                    | vectorized         | false
limit               |                    |
│                  | count              | 10
└── hash-join      |                    |
        │             | type               | inner
        │             | equality           | (receiver_id) = (id)
        │             | right cols are key |
        ├── hash-join |                    |
        │    │        | type               | inner
        │    │        | equality           | (sender_id) = (id)
        │    │        | right cols are key |
        │    ├── scan |                    |
        │    │        | table              | transaction@primary
        │    │        | spans              | ALL
        │    └── scan |                    |
        │             | table              | wallet@primary
        │             | spans              | ALL
        └── scan      |                    |
                    | table              | wallet@primary
                    | spans              | ALL

【问题讨论】:

标签: sql-server performance-testing cockroachdb


【解决方案1】:

我认为您的表格可能包含过时的统计信息。 (尽管希望到此为止,统计信息已自动更新,您不再遇到此问题。)您可以在CockroachDB docs 中阅读有关此内容的信息,并且那里还有一个链接描述了如何手动创建新的统计数据。

【讨论】:

    【解决方案2】:

    这似乎是由于 SQL Server 和 CockroachDB 之间的查询计划存在差异,但可以通过几种方式解决。

    根本问题是transaction 表有两个指向wallet 表的外键约束,但两个外键都可以为空。这可以防止 CockroachDB 通过连接推动 10 行限制,因为对 transaction 表的扫描可能需要生成超过 10 行,整个查询才能生成多达 10 行。

    我们在查询计划中看到了这一点:

    > explain select * from transaction t
      join wallet s on t.sender_id=s.id
      join wallet r on t.receiver_id=r.id
      limit 10;
                        info
    ---------------------------------------------
      distribution: full
      vectorized: true
    
      • limit
      │ count: 10
      │
      └── • lookup join
          │ table: wallet@primary
          │ equality: (receiver_id) = (id)
          │ equality cols are key
          │
          └── • lookup join
              │ table: wallet@primary
              │ equality: (sender_id) = (id)
              │ equality cols are key
              │
              └── • scan
                    estimated row count: 10,000
                    table: transaction@primary
                    spans: FULL SCAN
    

    请注意,在两个连接之后都会应用限制。

    有两种相对简单的方法可以解决此问题。首先,我们可以将joins 替换为left joins。这将允许将限制下推到对transaction 表的扫描,因为左连接永远不会丢弃行。

    > explain select * from transaction t
      left join wallet s on t.sender_id=s.id
      left join wallet r on t.receiver_id=r.id
      limit 10;
                      info
    ----------------------------------------
      distribution: full
      vectorized: true
    
      • lookup join (left outer)
      │ table: wallet@primary
      │ equality: (receiver_id) = (id)
      │ equality cols are key
      │
      └── • lookup join (left outer)
          │ table: wallet@primary
          │ equality: (sender_id) = (id)
          │ equality cols are key
          │
          └── • scan
                estimated row count: 10
                table: transaction@primary
                spans: LIMITED SCAN
                limit: 10
    

    另一个选项是在外键约束@​​987654329@ 中创建引用列。这也将允许将限制下推到对transaction 表的扫描,因为即使是内部连接也永远不会丢弃行。

    > alter table transaction alter column sender_id set not null;
    ALTER TABLE
    
    > alter table transaction alter column receiver_id set not null;
    ALTER TABLE
    
    > explain select * from transaction t
      join wallet s on t.sender_id=s.id
      join wallet r on t.receiver_id=r.id
      limit 10;
                      info
    ----------------------------------------
      distribution: full
      vectorized: true
    
      • lookup join
      │ table: wallet@primary
      │ equality: (receiver_id) = (id)
      │ equality cols are key
      │
      └── • lookup join
          │ table: wallet@primary
          │ equality: (sender_id) = (id)
          │ equality cols are key
          │
          └── • scan
                estimated row count: 10
                table: transaction@primary
                spans: LIMITED SCAN
                limit: 10
    

    【讨论】:

      猜你喜欢
      • 2020-07-19
      • 2014-01-01
      • 1970-01-01
      • 2014-12-17
      • 1970-01-01
      • 1970-01-01
      • 2012-09-29
      • 1970-01-01
      • 2019-08-05
      相关资源
      最近更新 更多