本次就給你們講講cassandra的高級操做:索引、排序和分頁;處於性能的考慮,cassandra對這些支持都比較簡單,因此咱們不能但願cassandra徹底適用於咱們的邏輯,而是應該將咱們的邏輯設計的更適合於cassandrahtml
路漫漫其修遠兮,吾將上下而求索!mysql
github:https://github.com/youzhibinggit
碼雲(gitee):https://gitee.com/youzhibinggithub
Cassandra對查詢的支持很弱,只支持主鍵列及索引列的查詢,並且主鍵列還有各類限制,不過查詢弱歸弱,但它仍是支持索引和排序的。sql
第一主鍵 只能用=號查詢apache
第二主鍵 支持= > < >= <=函數
索引列 只支持=號性能
Cassandra支持建立二級索引,能夠建立在除了第一主鍵(分區鍵:partition key)以外全部的列上;不一樣的cassandra版本對集合列的索引的支持也是不一樣的,有的支持有的不支持,你們能夠去看下官方文檔的Changes,2.1版本開始,能夠創建集合索引spa
建一張teacher表:設計
create table teacher( id int, address text, name text, age int, height int, primary key(id,address,name) );
向teacher表中插入數據:
insert into teacher(id,address,name,age,height) values(1,'guangdong','lixiao',32,172); insert into teacher(id,address,name,age,height) values(1,'guangxi','linzexu',68,178); insert into teacher(id,address,name,age,height) values(1,'guangxi','lihao',25,178); insert into teacher(id,address,name,age,height) values(2,'guangxi','lixiaolong',32,172); insert into teacher(id,address,name,age,height) values(2,'guangdong','lixiao',32,172); insert into teacher(id,address,name,age,height) values(2,'guangxi','linzexu',68,178); insert into teacher(id,address,name,age,height) values(2,'guangxi','lihao',25,178); insert into teacher(id,address,name,age,height) values(2,'guangxi','nnd',32,172);
建索引:
CREATE INDEX idx_teacher_age on teacher(age);
索引列只能夠用=號查詢,因此
select * from teacher where age=32; //能夠 select * from teacher where age>32; //不行
若是查詢條件裏,有一個是根據索引查詢,那其它非索引非主鍵字段,能夠經過加一個ALLOW FILTERING來過濾實現
select * from teacher where age=32 and height>30 ALLOW FILTERING;
先根據age=32過濾出結果集,而後再對結果集進行height>30過濾
建一張tt表:
create table tt( id int, address text, name text, age int, height int, primary key(id,address,name) )WITH CLUSTERING ORDER BY(address DESC, name ASC);
向tt表中插入數據:
insert into tt(id,address,name,age,height) values(1,'guangdong','lixiao',32,172); insert into tt(id,address,name,age,height) values(1,'guangxi','linzexu',68,178); insert into tt(id,address,name,age,height) values(1,'guangxi','lihao',25,178); insert into tt(id,address,name,age,height) values(2,'guangxi','lixiaolong',32,172); insert into tt(id,address,name,age,height) values(2,'guangdong','lixiao',32,172); insert into tt(id,address,name,age,height) values(2,'guangxi','linzexu',68,178); insert into tt(id,address,name,age,height) values(2,'guangxi','lihao',25,178); insert into tt(id,address,name,age,height) values(2,'guangxi','nnd',32,172);
Cassandra支持排序,但也是限制重重
a、 必須有第一主鍵的=號查詢;cassandra的第一主鍵是決定記錄分佈在哪臺機器上,也就是說cassandra只支持單臺機器上的記錄排序。
b、 只能根據第2、3、四…主鍵進行有序的,相同的排序。
有序:order by後面只能是先2、再3、再四…這樣的順序,有四,前面必須有三;有三,前面必須有二,以此類推。
相同的順序:參與排序的主鍵要麼與建表時指定的順序一致,要麼所有相反,具體會體如今下面的示例中
c、 不能有索引查詢
正確示例:
SELECT * FROM teacher WHERE id=1 ORDER BY address ASC; SELECT * FROM teacher WHERE id=1 ORDER BY address ASC, name ASC; SELECT * FROM teacher WHERE id=1 AND address='guangxi' ORDER BY address ASC; SELECT * FROM teacher WHERE id=1 AND address='guangxi' ORDER BY address ASC, name ASC; SELECT * FROM teacher WHERE id=1 ORDER BY address DESC; SELECT * FROM teacher WHERE id=1 ORDER BY address DESC, name DESC; SELECT * FROM teacher WHERE id=1 AND address='guangxi' ORDER BY address DESC; SELECT * FROM teacher WHERE id=1 AND address='guangxi' ORDER BY address DESC, name DESC;
SELECT * FROM tt WHERE id=1 ORDER BY address DESC; SELECT * FROM tt WHERE id=1 ORDER BY address DESC, name ASC; SELECT * FROM tt WHERE id=1 AND address='guangxi' ORDER BY address DESC; SELECT * FROM tt WHERE id=1 AND address='guangxi' ORDER BY address DESC, name ASC; SELECT * FROM tt WHERE id=1 ORDER BY address ASC; SELECT * FROM tt WHERE id=1 ORDER BY address ASC, name DESC; SELECT * FROM tt WHERE id=1 AND address='guangxi' ORDER BY address ASC; SELECT * FROM tt WHERE id=1 AND address='guangxi' ORDER BY address ASC, name DESC;
錯誤示例:
SELECT * FROM teacher ORDER BY address DESC; //沒有第一主鍵 不行 SELECT * FROM teacher WHERE id=1 ORDER BY name DESC; //必須以第二主鍵開始排序 SELECT * FROM teacher WHERE id=1 ORDER BY address DESC, name ASC; //不是與建表時指定的排序一致或者徹底相反 (默認是address ASC, name ASC) SELECT * FROM teacher WHERE age=1 ORDER BY address DESC; //不能有索引 SELECT * FROM tt WHERE id=1 ORDER BY address DESC, name DESC; //不是與建表時指定的排序一致或者徹底相反 (建表時指定了address DESC, name ASC)
其實cassandra的任何查詢,最後的結果都是有序的,默認與建表時指定的排序規則一致(例如teacher表是address ASC,name ASC,而tt表則是address DESC,name ASC),由於它內部就是這樣存儲的。因此你對teacher表使用address DESC, name ASC 或者address ASC,name DESC排序,對tt表使用address DESC, name DESC 或者address ASC,name ASC排序,cassandra都是比較爲難的。
固然這個默認存儲排序方式,是能夠在建表的時候指定的,就想tt表那樣。
一說分頁,我很容易就想到了mysql中的limit,恰巧cassandra也是用它來實現分頁的,可是cassandra的limit沒有mysql的那麼強大,它只能限制查詢結果的條數,而不能指定從哪裏開始,那麼問題就來了:cassandra到底要怎麼實現分頁了?
上面咱們已經分析了,要實現分頁還差一個條件:起始點;cassandra中經過token函數來肯定起始點,具體這個token函數是幹嗎的,你們自行去補腦。接下來我直接看例子,看完例子,相信你們會對token有必定的認知了。
先看下teacher表中的所有數據:
一共8條數據,那麼咱們就按一頁2條記錄(pageSize=2)來查出所有數據
起始查詢比較好理解:select * from teacher limit 2;結果以下:
此時,須要將上面查詢獲得的結果的最後一條記錄的主鍵id,address,name的值記錄1,guagnxi,lihao記錄下來,下次查詢須要用到
select * from teacher where token(id)=token(1) and (address,name)>('guangxi','lihao') limit 2 ALLOW FILTERING; 結果以下:
只查詢出了1條記錄,不夠2條,繼續查詢,這時語句應該這麼寫:select * from teacher where token(id)>token(1) limit 1;結果以下:
將2,guangdong,lixiao記錄下來,供下次查詢用
和第二次查詢同樣,先查詢token(id)相等(where token(id)=token(1)),直到出現查詢的記錄數小於pageSize,再查詢token(id)大的(token(id)>token(1))
一、第一次查詢,獲得的記錄數若小於pageSize,那麼就說明後面沒數據,若等於pageSize,那就不知道是否還有數據,則須要進行第二次查詢。
二、第二次查詢,先從token(id)=開始查,若在token(id)=的查詢中出現記錄數(searchedCounts)小於pageSize,則轉向token(id)>的開始查,若token(id)>的查詢記錄數小於(pageSize – searchedCounts),那麼就說明沒有數據了,若token(id)>的查詢記錄數等於(pageSize – searchedCounts),那麼重複第二次查詢。
綜上所述,知道後面沒有數據的點只有兩個,一、第一次查詢的時候;二、token(id)>的時候,其餘時候都不能判定後面沒有數據
cassandra 的分頁查詢,主要是經過查詢結果的默認的排列順序來實現的,本文的例子是沒有查詢條件的狀況,有查詢條件的狀況,也是同樣的。你只要知道了cassandra的默認查詢結果的排序規則,就知道如何具體的分頁查詢了,默認排序在建表的時候是能夠指定的,就想tt表那樣,對tt的分頁查詢我就不演示了,但願你們本身去實現tt表的分頁查詢,裏面有不少有趣的東西哦! tt表的默認排序規則與teacher表是不一樣的,那麼tt表的分頁與teacher表是有區別的!