Тот же запрос SQL, CockroachDB занимает 4 минуты, SQL Server занимает 35 мс. Я что-то упускаю?

База данных содержит всего 2 таблицы:

  • кошелек (1 миллион строк)
  • транзакция (15 миллионов строк)

CockroachDB 19.2.6 работает на 3 машинах с Ubuntu

  • 2 ВЦП каждый
  • 8 ГБ ОЗУ каждый
  • Контейнер Docker Swarm

vs

SQL Server 2019 работает на 1 машине Windows Server 2019

  • 4 ВЦП
  • 16 ГБ ОЗУ

Вот запрос

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 требуется всего 35 мс, чтобы вернуть первые 10 результатов.
  • CockroachDB тратит на это 3,5-5 минут.

1) Я знаю, что инфраструктура недостаточно справедлива для CockroachDB, но, тем не менее, разница действительно слишком велика. Я что-то упускаю? или CockroachDB просто очень медленный для этого конкретного SQL-запроса?

2) Когда я выполняю этот запрос, ЦП всех 3 узлов тараканов увеличился до 100%. Это нормально?

Обновление: вот запрос "EXPLAIN". не знаю как читать..

> 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

person Hiep    schedule 06.05.2020    source источник
comment
Ваша схема/индексы сильно влияют на это. Покрыты ли столбцы, к которым вы присоединяетесь, индексами? Вы можете использовать их документы EXPLAIN, чтобы увидеть, какие индексы выбираются, чтобы помочь определить, почему все работает медленно cockroachlabs.com/docs/v19.2/explain.html   -  person Loiselle    schedule 08.05.2020
comment
конечно, они покрыты индексами, плюс все они являются внешними ключами: /ee14af3f783f5abedce274beebd903e5 Я использовал объяснение, но с ограниченным пониманием я не уверен, как читать и отлаживать, чтобы определить, хорошо это объяснение или нет.   -  person Hiep    schedule 09.05.2020


Ответы (2)


Похоже, что на самом деле это связано с разницей в планах запросов между SQL Server и CockroachDB, но это можно обойти несколькими способами.

Основная проблема заключается в том, что таблица transaction имеет два ограничения внешнего ключа, указывающих на таблицу wallet, но оба внешних ключа допускают значение NULL. Это не позволяет 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

Другой вариант — сделать ссылочные столбцы в ограничениях внешнего ключа non null. Это также позволит снизить ограничение до сканирования таблицы 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
person Nathan VanBenschoten    schedule 15.12.2020

Я считаю, что в вашей таблице может быть устаревшая статистика. (Хотя, надеюсь, к этому моменту статистика автоматически обновится, и у вас больше не будет этой проблемы.) Вы можете прочитать об этом в Документация по CockroachDB, а также там есть ссылка, описывающая, как вручную создать новую статистику.

person rafiss    schedule 09.12.2020