2015-07-28 6 views
2

Я знаю, что cassandra не поддерживает соединения, поэтому для использования cassandra нам необходимо денормализовать таблицы. Я хотел бы знать, как? Предположим, у меня есть две таблицыCassandra - Как денормализовать две соединенные таблицы?

<dl> 
 
<dt>Publisher</dt> 
 
<dd>Id : <i>Primary Key</i></dd> 
 
    <dd>Name</dd> 
 
    <dd>TimeStamp</dd> 
 
    <dd>Address</dd> 
 
    <dd>PhoneNo</dd> 
 
    
 
    <dt>Book</dt> 
 
    <dd>Id : <i>Primary Key</i></dd> 
 
    <dd>Name</dd> 
 
    <dd>ISBN</dd> 
 
    <dd>Year</dd> 
 
    <dd>PublisherId : <i>Foreign Key - Referenes Publisher table's Id</i></dd> 
 
    <dd>Cost</dd> 
 
    </dt> 
 
</dl>

Пожалуйста, дайте мне знать, как я могу денормализовать эти таблицы для достижения следующих операций эффективно
1. Поиск всех книг, изданных конкретным издателем ,
2. Поиск всех издателей, издавших книги за определенный год.
3. Поиск всех издателей, которые не издавали книги за определенный год.
4. Поиск всех издателей, которые до сих пор не издавали книги.

Я видел несколько статей о кассандре. Но не в состоянии завершить денормализацию для вышеуказанных операций. Пожалуйста, помогите мне.

+0

Поиск всех издателей, которые до сих пор не издавали книги (т. Е. Искать всех издателей, которые не публикуют ни одной книги) –

ответ

1

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

Таким образом, вы бы создать таблицу для каждого типа запроса, что-то вдоль этих линий:

  1. Создать таблицу, разделенную на идентификатор издателя и с книгой идентификатор в виде столбца кластеризации.
  2. Создайте таблицу, разбитую по годам, и с идентификатором издателя в качестве столбца кластеризации.
  3. Создайте таблицу со списком всех издателей. В приложении вы могли бы затем прочитать этот список и программно вычесть строки, имеющиеся в желаемом году, считанные из таблицы 2.
  4. Я не уверен, что означает «опубликованный до сих пор». Когда вы вставляете новую книгу, вы можете проверить, присутствует ли издатель в таблице 3. Если нет, то это новый издатель.

Таким образом, в каждой строке данных вы будете повторять все данные, которые вы хотели бы вернуть с запросом (т. Е. Объединение всех столбцов в таблицах примеров). Когда вы вставляете новую книгу, вы вставляете ее во все ваши таблицы.

+0

Поиск всех издателей, которые до сих пор не публиковали книги (т.е. все издатели, которые не публикуют ни одной книги). –

+0

Кроме того, для двух таблиц в СУБД я создаю 3 или 4 таблицы в C *, как вы упомянули, и даже для одного витта мне нужно сделать это в 2 таблицах. И большинство операций соединения выполняются на стороне клиента, а затем на уровне DB. Правильно ли это? Я надеюсь, что это принесет некоторую производительность? Любой другой лучший способ сделать это? –

+0

Запись на несколько таблиц может привести к некоторому снижению производительности, но если вы выдаете асинхронные записи, они должны быть довольно быстрыми, поскольку они будут хешировать для разных узлов. Кроме того, поскольку ваш вопрос звучит так, как будто ваше приложение в основном читает, денормализация сделает чтение быстрым, так как каждый прочитанный получит доступ к одному разделу. –

0

Похоже, что это может стать огромным, поэтому я возьму первый и пройду, как бы подойти к нему. У вас не есть, чтобы сделать это так, это всего лишь один из способов обойти это. Обратите внимание, что вам, возможно, придется создавать таблицы запросов для каждого из ваших 4 описанных выше сценариев. Эта таблица будет решена только для первого сценария.

Прежде всего, я создам тип для адреса издателя.

CREATE TYPE address (
    street text, 
    city text, 
    state text, 
    postalCode text 
); 

Далее Я создам таблицу под названием booksByPublisher. Я буду использовать свой address тип для publisherAddress. И я создам свой ПЕРВЫЙ КЛЮЧ с publisherid в качестве ключа раздела, кластер на bookYear и isbn.

Поскольку вы хотите иметь возможность запрашивать все книги определенного издателя, имеет смысл обозначить это как ключ раздела.Может оказаться полезным, чтобы ваши результаты отсортированы в год или, по крайней мере, смогут посмотреть конкретный год для определенного издателя, поэтому у меня есть bookYear в качестве первого ключа кластеризации. И, конечно, чтобы создать уникальную строку CQL для каждой книги в издателе, я добавлю isbn для уникальности.

CREATE TABLE booksByPublisher (
    publisherid UUID, 
    publisherName text, 
    publisherAddress frozen<address>, 
    publisherPhoneNo text, 
    bookName text, 
    isbn text, 
    bookYear bigint, 
    bookCost bigint, 
    bookAuthor text, 
    PRIMARY KEY (publisherid, bookYear, isbn) 
); 

INSERT INTO booksByPublisher (publisherid, publishername, publisheraddress, publisherphoneno, bookname, isbn, bookyear, bookcost, bookauthor) 
VALUES (b7b99ee9-f495-444b-b849-6cea82683d0b,'Crown Publishing',{ street: '1745 Broadway', city: 'New York', state:'NY', postalcode: '10019'},'212-782-9000','Ready Player One','978-0307887443',2005,812,'Ernest Cline'); 

INSERT INTO booksByPublisher (publisherid, publishername, publisheraddress, publisherphoneno, bookname, isbn, bookyear, bookcost, bookauthor) 
VALUES (b7b99ee9-f495-444b-b849-6cea82683d0b,'Crown Publishing',{ street: '1745 Broadway', city: 'New York', state:'NY', postalcode: '10019'},'212-782-9000','Armada','978-0804137256',2015,1560,'Ernest Cline'); 

INSERT INTO booksByPublisher (publisherid, publishername, publisheraddress, publisherphoneno, bookname, isbn, bookyear, bookcost, bookauthor) 
VALUES (uuid(),'The Berkley Publishing Group',{ street: '375 Hudson Street', city: 'New York', state:'NY', postalcode: '10014'},'212-333-2354','Rainbox Six','978-0425170342',1999,867,'Tom Clancy'); 

Теперь я могу запросить все книги (из моих 3-х строк), опубликованный Crown Publishing (publisherid=b7b99ee9-f495-444b-b849-6cea82683d0b), как это:

[email protected]:stackoverflow2> SELECT * FROM booksbypublisher 
    WHERE publisherid=b7b99ee9-f495-444b-b849-6cea82683d0b; 

publisherid       | bookyear | isbn   | bookauthor | bookcost | bookname   | publisheraddress                | publishername | publisherphoneno 
--------------------------------------+----------+----------------+--------------+----------+------------------+-------------------------------------------------------------------------------+------------------+------------------ 
b7b99ee9-f495-444b-b849-6cea82683d0b |  2005 | 978-0307887443 | Ernest Cline |  812 | Ready Player One | {street: '1745 Broadway', city: 'New York', state: 'NY', postalcode: '10019'} | Crown Publishing |  212-782-9000 
b7b99ee9-f495-444b-b849-6cea82683d0b |  2015 | 978-0804137256 | Ernest Cline |  1560 |   Armada | {street: '1745 Broadway', city: 'New York', state: 'NY', postalcode: '10019'} | Crown Publishing |  212-782-9000 

(2 rows) 

Если я хочу, я могу также запросить для всех книг Короны Издательство в течение 2015 года:

[email protected]:stackoverflow2> SELECT * FROM booksbypublisher 
    WHERE publisherid=b7b99ee9-f495-444b-b849-6cea82683d0b AND bookyear=2015; 

publisherid       | bookyear | isbn   | bookauthor | bookcost | bookname | publisheraddress                | publishername | publisherphoneno 
--------------------------------------+----------+----------------+--------------+----------+----------+-------------------------------------------------------------------------------+------------------+------------------ 
b7b99ee9-f495-444b-b849-6cea82683d0b |  2015 | 978-0804137256 | Ernest Cline |  1560 | Armada | {street: '1745 Broadway', city: 'New York', state: 'NY', postalcode: '10019'} | Crown Publishing |  212-782-9000 

(1 rows) 

Но я не могу запрос, просто bookyear:

[email protected]:stackoverflow2> SELECT * FROM booksbypublisher WHERE bookyear=2015; 
InvalidRequest: code=2200 [Invalid query] message="Cannot execute this query as it might 
involve data filtering and thus may have unpredictable performance. If you want to execute 
this query despite the performance unpredictability, use ALLOW FILTERING" 

И не слушайте сообщение об ошибке и добавьте ALLOW FILTERING. Это может работать нормально для таблицы с тремя строками (или даже 300). Но он не будет работать для таблицы с 3 миллионами строк (вы получите тайм-аут). Cassandra работает лучше всего, когда вы запрашиваете полный ключ раздела. Поскольку publisherid является нашим ключом раздела, этот запрос будет работать отлично. Но если вам нужно запросить bookYear, тогда вы должны создать таблицу, которая в качестве ключа разбиения использует bookYear.

Смежные вопросы