Почему Cassandra COUNT (*) на определенном разделе занимает действительно много времени на сравнительно небольших наборах данных - PullRequest
1 голос
/ 14 мая 2019

У меня есть таблица, определенная как:

Пространство ключей :

CREATE KEYSPACE messages WITH replication = {'class': 'SimpleStrategy', 'replication_factor': '1'} AND durable_writes = true;

Таблица :

CREATE TABLE messages.textmessages (
    categoryid int,
    date timestamp,
    messageid timeuuid,
    message text,
    userid int,
    PRIMARY KEY ((categoryid, date), messageid)
) WITH CLUSTERING ORDER BY (messageid ASC);

Цель состоит в том, чтобы иметь широкое хранилище временных рядов, чтобы categoryid и date (начало дня) составляли ключ моего раздела, а messageid обеспечивает кластеризацию.Это позволяет мне выполнять запросы вроде:

SELECT * FROM messages.textmessages WHERE categoryid=2 AND date='2019-05-14 00:00:00.000+0300' AND messageId > maxTimeuuid('2019-05-14 00:00:00.000+0300') AND messageId < minTimeuuid('2019-05-15 00:00:00.000+0300')

для получения сообщений в определенный день;это работает так хорошо, так быстро!

Проблема

Мне нужно иметь возможность подсчитывать сообщения за определенный день, подставляя SELECT * выше с SELECT COUNT(*).Это занимает очень много времени даже при чуть менее 100 000 записей в семействе столбцов;на самом деле время ожидания cqlsh.

Я прочитал и понял довольно много, почему COUNT является дорогой операцией для распределенной базы данных, такой как Cassandra, в Подсчет ключей?Также возможно считать звезды

Вопрос

Почему этот запрос занимает столько времени, даже если:

SELECT COUNT(*) FROM messages.textmessages WHERE categoryid=2 AND date='2019-05-14 00:00:00.000+0300' AND messageId > maxTimeuuid('2019-05-14 00:00:00.000+0300') AND messageId < minTimeuuid('2019-05-15 00:00:00.000+0300')
  1. Счетчик находится на определенном разделе с количеством записей менее 100 КБ
  2. У меня только один узел Cassandra на быстродействующем Macbook Pro
  3. Нет активных операций записи / чтения в экземпляре;менее 20 разделов на ноутбуке для разработчиков

1 Ответ

2 голосов
/ 14 мая 2019

По понятным причинам это вызвано распространенной ошибкой , когда в Кассандре игнорируется концепция «все, что пишется» и, следовательно, почему возникают надгробия.

При выполнении сканирования внутри или между разделами нам нужно сохранять захоронения, видимые в памяти, чтобы мы могли вернуть их координатору, который будет использовать их, чтобы другие реплики также знали об удаленных строках. С рабочими нагрузками, которые генерируют много надгробий, это может вызвать проблемы с производительностью и даже исчерпать кучу серверов.

Благодаря предложению @ JimWartnick о возможной задержке, связанной с надгробием; это было вызвано подавляющим количеством надгробий, созданных моими вставками, которые имели поля NULL. Я не ожидал, что это вызовет надгробия, и при этом я не ожидал, что надгробия будут иметь большое значение в производительности запросов; особенно COUNT.

Решение

  1. Использовать значения по умолчанию в полях, если они отсутствуют, или вообще не указывать их во вставках / обновлениях
  2. Будьте осведомлены о следующих фактах, изложенных в Общие проблемы с надгробиями Кассандры - Алла Бабкина

Одним из распространенных заблуждений является то, что надгробия появляются только тогда, когда клиент выдает операторы DELETE Cassandra. Некоторые разработчики предполагают, что можно безопасно выбирать способ работы, при котором Cassandra полностью свободна от надгробий. В действительности есть много других вещей, вызывающих надгробия, кроме выдачи операторов DELETE. Вставка нулевых значений, вставка коллекций и истечение срока действия данных с использованием TTL являются распространенными источниками надгробий.

...