Где и заказать по пунктам в Cassandra CQL
Я новичок в базе данных NoSQL и только начал использовать Apache Cassandra. Я создал простую таблицу "emp" с первичным ключом в столбце "empno". Это простая таблица, поскольку мы всегда получаем в схеме Скотта по умолчанию Oracle.
Теперь я загрузил данные, используя COPY
команда и выданный запрос Select * from emp order by empno
но я был удивлен, что CQL не позволил Order by на empno
столбец (который является ПК). Также когда я использовал Where
условие, оно не разрешало какие-либо операции неравенства над столбцом empno (указывалось, что допускаются только условия EQ или IN). Кроме того, он не разрешал "Где и порядок" в других столбцах, так как они не использовались в PK и не имели индекса.
Может кто-нибудь, пожалуйста, помогите мне, что мне делать, если я хочу сохранить empno
уникален в таблице и требует результатов запроса в отсортированном порядке empno
?
(Моя версия:
cqlsh:demodb> show version
[cqlsh 5.0.1 | Cassandra 2.2.0 | CQL spec 3.3.0 | Native protocol v4]
)
1 ответ
ПЕРВИЧНЫЙ КЛЮЧ на Кассандре состоит из двух частей:
- ключ (ы) раздела
- ключ (ы) кластеризации
PRIMARY KEY (partitionKey1,clusteringKey1,clusteringKey2)
или же
PRIMARY KEY ((partitionKey1,partitionKey2),clusteringKey1,clusteringKey2)
Ключ раздела определяет, на каком узле хранятся ваши данные. Ключ кластеризации определяет порядок данных в ключе вашего раздела.
В CQL ORDER BY
Предложение действительно используется только для изменения направления сортировки вашего порядка кластеризации. Что касается самих столбцов, вы можете указать только определенные столбцы (и в этом точном порядке... без пропусков) в вашем CLUSTERING ORDER BY
предложение во время создания таблицы. Таким образом, вы не можете выбрать произвольные столбцы для упорядочения набора результатов во время запроса.
Cassandra достигает производительности, используя ключи кластеризации для сортировки данных на диске, тем самым возвращая упорядоченные строки только за одно чтение (без случайного чтения). Вот почему вы должны использовать подход моделирования на основе запросов (часто дублируя ваши данные в нескольких таблицах запросов) с Cassandra. Знайте свои запросы заранее и создавайте таблицы для их обслуживания.
Select * from emp order by empno;
Прежде всего, вам нужен WHERE
пункт. Запрашивать без него нормально, если вы работаете с реляционной базой данных. С Кассандрой вы должны сделать все возможное, чтобы избежать SELECT
запросы. Кроме того, Cassandra может только навести порядок сортировки внутри раздела, так что запрос без WHERE
В любом случае, условие не будет возвращать данные в нужном вам порядке.
Во-вторых, как я упоминал выше, вам нужно определить ключи кластеризации. Если вы хотите заказать свой результат по empno
, затем вы должны найти другой столбец, который будет определяться как ключ раздела. Попробуйте что-то вроде этого:
CREATE TABLE emp_by_dept (
empno text,
dept text,
name text,
PRIMARY KEY (dept,empno)
) WITH CLUSTERING ORDER BY (empno ASC);
Теперь я могу запросить сотрудников по отделам, и они будут возвращены мне по заказу empno
:
SELECT * FROM emp_by_dept WHERE dept='IT';
Но, чтобы быть ясным, вы не сможете запросить каждую строку в вашей таблице, и упорядочить ее по одному столбцу. Единственный способ получить значимый порядок в ваших результирующих наборах - это сначала разделить ваши данные таким образом, чтобы это имело смысл для вашего бизнес-кейса. Запуск несвязанного SELECT
вернет все ваши строки (при условии, что запрос не истечет время ожидания при попытке запроса каждого узла в кластере), но упорядочение результирующего набора может быть применено только в пределах раздела. Таким образом, вы должны ограничить ключом раздела, чтобы это имело смысл.
Приношу свои извинения за саморекламу, но в прошлом году я написал статью для DataStax под названием We Shall Have Order!, в котором я рассмотрел, как решить эти типы проблем. Прочитайте его и посмотрите, поможет ли это.
Изменить для дополнительных вопросов:
Из вашего ответа я сделал вывод о двух вещах о Кассандре:
(1) Нет способа получить набор результатов, который упорядочен только по столбцу, который был определен как уникальный.
(2) Когда мы определяем PK (ключ-раздел + ключ-кластер), результаты всегда будут упорядочены по столбцам кластеризации внутри любого фиксированного ключа раздела (мы должны ограничиться одним значением ключа раздела), что означает, что необходимость в предложении ORDER BY, так как он не может изменить порядок строк (порядок, в котором строки фактически сохраняются), т. е. Order By бесполезен.
1) Все ПЕРВИЧНЫЕ КЛЮЧИ в Кассандре уникальны. Нет способа упорядочить ваш набор результатов по ключу раздела. В моем примере я заказываю empno
(после разделения по отделу). - Аарон 1 час назад
2) Не говоря уже о том, что ORDER BY бесполезен, я скажу, что его единственное реальное использование - переключение направления сортировки между ASC и DESC.
Я создал индекс для столбца "empno" таблицы "emp", он по-прежнему не позволяет ORDER BY empno. Итак, для чего нужны индексы? они только для поиска записей для определенного значения ключа индекса?
Вы не можете упорядочить результирующий набор по индексируемому столбцу. Вторичные индексы (не совпадают с их реляционными аналогами) действительно полезны только для крайних случаев, основанных на аналитике запросов. Они не масштабируются, поэтому общая рекомендация - не использовать вторичные индексы.
Хорошо, это просто означает, что одну таблицу нельзя использовать для получения разных наборов результатов с разными условиями и разным порядком сортировки.
Правильный.
Следовательно, для каждого нового требования нам нужно создать новую таблицу. ИТ означает, что если у нас есть миллиард строк в таблице (скажем, в таблице продаж), и нам нужна сумма продаж (1) по продуктам, (2) по регионам, то мы дублируем все эти миллиарды строк в 2 таблицах с одной в порядке кластеризации Продукта, другой в порядке кластеризации Региона. и даже если нам нужно суммировать продажи по Salesman_id, тогда мы создадим третью таблицу, снова поместив все эти миллиарды строк? это разумно?
Вам решать, насколько это разумно. Но отсутствие гибкости запросов является недостатком Cassandra. Чтобы обойти это, вы можете продолжать создавать таблицы запросов (IE, торговый диск для повышения производительности). Но если он доходит до того, что им становится неуклюже или трудно управлять, то пришло время подумать о том, действительно ли Кассандра - правильное решение.
РЕДАКТИРОВАТЬ 20160321
Привет, Аарон, ты сказал выше: "Не говоря уже о том, что ORDER BY бесполезен, я скажу, что его единственное реальное использование - переключение направления сортировки между ASC и DESC".
Но я обнаружил, что даже это не правильно. Кассандра позволяет ЗАКАЗАТЬ только в том же направлении, которое мы определили в вызове "ЗАКЛЮЧЕНИЕ ЗАКАЗА" в CREATE TABLE. Если в этом пункте мы определяем ASC, он разрешает только порядок по ASC, и наоборот.
Не видя сообщения об ошибке, трудно понять, что вам сказать по этому поводу. Хотя я слышал о запросах с ORDER BY
сбой, если в разделе хранится слишком много строк.
ORDER BY
также функционирует немного странно, если вы указываете несколько столбцов для сортировки. Если у меня есть два столбца кластеризации, я могу использовать ORDER BY
на первом столбце без разбора. Но как только я добавлю второй столбец к ORDER BY
мой запрос работает, только если я указываю оба направления сортировки одинаково (как CLUSTERING ORDER BY
определение) или оба разные. Если я смешиваю и сопоставляю, я получаю это:
InvalidRequest: code=2200 [Invalid query] message="Unsupported order by relation"
Я думаю, что это связано с тем, как данные хранятся на диске. В противном случае у Кассандры было бы больше работы по подготовке наборов результатов. Принимая во внимание, что если требуется, чтобы все соответствовало или отражало направление (я), указанное в CLUSTERING ORDER BY
, он может просто передавать последовательное чтение с диска. Так что, вероятно, лучше всего использовать один столбец в вашем ORDER BY
пункт, для более предсказуемых результатов.
Добавление избыточного ответа в качестве принятого довольно длинное.
Упорядочение по в настоящее время поддерживается только для кластеризованных столбцов PRIMARY KEY и когда ключ разделения ограничен оператором Equality или IN в предложении where.
Это если ваш первичный ключ определен так:
PRIMARY KEY ((a,b),c,d)
Тогда вы сможете использовать ORDER BY только тогда, когда ваш запрос имеет:
предложение where со всем первичным ключом, ограниченным либо оператором равенства (=), либо оператором IN, например:
SELECT * FROM emp WHERE a = 1 AND b = 'India' ORDER BY c,d;
SELECT * FROM emp WHERE a = 1 AND b = 'India' ORDER BY c;
Эти два запроса являются единственными действительными.
Также этот запрос не будет работать:
SELECT * FROM emp WHERE a = 1 AND b = 'India' ORDER BY d,c;
потому что order by в настоящее время поддерживает только порядок столбцов, следующих за их объявленным порядком в PRIMARY KEY, который находится в определении первичного ключа c, который был объявлен до d, и запрос нарушает порядок, помещая d первым.