Share
Embed
CodernityDB, Pure Python NoSQL database
Jędrzej Nowak "pigmej"
CodernityDB, Pure Python NoSQL database
html version here: http://jedrzejnowak.pl/talks/Pykonik012013/
Pykonik
January 18, 2013
Transcript
33 slides
-
Pure Python NoSQL database Pykonik 01 2013 Jędrzej Nowak "pigmej"
/ Codernity.com @codernity -
Dlaczego ? schema less embedded nature python support collections /
tables data encryption -
Początek ? ~ / w o r k s p
a c e / C o d e r n i t y D B % t r e e . ├ ─ ─ d b │ └ ─ ─ _ _ i n i t _ _ . p y └ ─ ─ s e t u p . p y 1 d i r e c t o r y , 2 f i l e s -
Teraz ? + docs + CodernityDB-PyClient + CodernityDB-HTTP ~ /
w o r k s p a c e / C o d e r n i t y D B % t r e e . ├ ─ ─ C o d e r n i t y D B [ . . . ] 4 d i r e c t o r i e s , 4 5 f i l e s ~ / w o r k s p a c e / C o d e r n i t y D B % s l o c c o u n t * * / * . p y [ . . . ] T o t a l P h y s i c a l S o u r c e L i n e s o f C o d e ( S L O C ) = 9 , 2 7 8 -
Proces testowy #1 1. Repozytorium HG 2. Jenkins master CI
3. Tox 1. CPython2.6 2. CPython2.7 3. PyPy1.8 4. PyPy1.9 5. PyPy-dev -
Proces testowy #2 Developer → HG → Jenkins → Tox
→ Sukces ... lub nie Jenkins → powiadomienie via Jabber → FIX -
CodernityDB design Database Never overwrite ACID (no forced f s
y n c ) Index Jeden główny i d indeks Wiele dodatkowych indeksów Storage m a r s h a l do zapisywania obiektów Łatwość implementacji alternatywnych storage (np szyfrowanych) -
Dataflow - get Get jest wykonywany prosto z indeksu. Brak
spowolnienia związanego z ilością indeksów -
Dataflow - insert Liniowo do każdego indeksu po kolei _
i d = s e l f . _ i n s e r t _ i d _ i n d e x ( _ r e v , d a t a ) f o r i n d e x i n s e l f . i n d e x e s [ 1 : ] : s e l f . _ s i n g l e _ i n s e r t _ i n d e x ( i n d e x , d a t a , _ i d ) -
Dataflow - update Tak samo jak insert Delete jest tożsame
_ i d = s e l f . _ i n s e r t _ i d _ i n d e x ( _ r e v , d a t a ) f o r i n d e x i n s e l f . i n d e x e s [ 1 : ] : s e l f . _ s i n g l e _ u p d a t e _ i n d e x ( i n d e x , d a t a , _ i d ) -
Szybkość blisko 100 000 operacji insert / aktualizacji na sekundę
ponad 100 000 operacji pobierania na sekundę testy wydajnościowe -
CodernityDB Index CodernityDB Index != SQL index Pobieranie określonych danych
Sortowanie danych Odseparowanie danych od siebie (tabele / kolekcje) -
Przykład c l a s s W i t h
X I n d e x ( H a s h I n d e x ) : d e f _ _ i n i t _ _ ( s e l f , * a r g s , * * k w a r g s ) : k w a r g s [ ' k e y _ f o r m a t ' ] = ' I ' s u p e r ( W i t h X I n d e x , s e l f ) . _ _ i n i t _ _ ( * a r g s , * * k w a r g s ) d e f m a k e _ k e y _ v a l u e ( s e l f , d a t a ) : a _ v a l = d a t a . g e t ( " x " ) i f a _ v a l i s n o t N o n e : r e t u r n a _ v a l , N o n e r e t u r n N o n e d e f m a k e _ k e y ( s e l f , k e y ) : r e t u r n k e y -
Nadal za trudne ? Łatwe, prawda? n a m e
: w i t h _ x t y p e : H a s h I n d e x k e y _ f o r m a t : I m a k e _ k e y _ v a l u e : x , N o n e -
Jak użyć tego indeksu ? d b = D a
t a b a s e ( ' / t m p / b ' ) d b . c r e a t e ( ) d b . a d d _ i n d e x ( W i t h X I n d e x ( d b . p a t h , ' w i t h _ x ' ) ) / / d b . a d d _ i n d e x ( s 1 ) # i f s 1 i s t h e " s i m p l e c o d e " f o r x i n x r a n g e ( 1 0 ) : d b . i n s e r t ( d i c t ( x = x ) ) f o r c u r r i n d b . a l l ( ' w i t h _ x ' ) : p r i n t c u r r -
Jak zacząć ? f r o m C o d
e r n i t y D B . d a t a b a s e i m p o r t D a t a b a s e d b = D a t a b a s e ( ' / t m p / a ' ) d b . c r e a t e ( ) f o r x i n x r a n g e ( 1 0 ) : d b . i n s e r t ( d i c t ( x = x ) ) f o r c u r r i n d b . a l l ( ' i d ' ) : p r i n t c u r r -
Tabele / kolekcje ? Po prostu użyj indeksów! c l
a s s T 1 I n d e x ( H a s h I n d e x ) : d e f _ _ i n i t _ _ ( s e l f , * a r g s , * * k w a r g s ) : k w a r g s [ ' k e y _ f o r m a t ' ] = ' I ' d e f m a k e _ k e y _ v a l u e ( s e l f , d a t a ) : i f d a t a . g e t ( ' t ' ) = = ' t 1 ' : r e t u r n d a t a [ ' x ' ] , N o n e d e f m a k e _ k e y ( s e l f , k e y ) : r e t u r n k e y -
Co teraz ? . . . d b . a
d d ( T 1 I n d e x ( d b . p a t h , ' t 1 ' ) ) d b . a d d ( t 2 ) # c o d e f o r t = ' t 2 ' f o r x i n x r a n g e ( 1 0 ) : d b . i n s e r t ( d i c t ( t = ' t 1 ' , x = x ) ) f o r a i n x r a n g e ( 1 0 ) : d b . i n s e r t ( d i c t ( t = ' t 2 ' , a = a ) ) f o r c u r r i n d b . a l l ( ' t 1 ' ) : p r i n t c u r r # j u s t r e s u l t s f o r t = t 1 f o r c u r r i n d b . a l l ( ' t 2 ' ) : p r i n t c u r r # j u s t r e s u l t s f o r t = t 2 -
key, value ? Dlaczego m a k e _ k
e y _ v a l u e zwraca 2 wartości ? d e f m a k e _ k e y _ v a l u e ( s e l f , d a t a ) : r e t u r n d a t a . g e t ( ' a ' ) , { v : d a t a . g e t ( ' v ' , 0 ) * 1 0 } # . . . -
All... Tylko all ? Oczywiście, że nie ;-) g e
t g e t _ m a n y get_between a l l Nadal mało ? -
Funkcje po stronie bazy Możesz napisać dowolną funkcję która uruchomi
się wewnątrz bazy danych. c l a s s W i t h X I n d e x ( T r e e B a s e d I n d e x ) : # t h e r e s t o f i n d e x c o d e d e f r u n _ a v g ( s e l f , d b , s t a r t , e n d ) : l = [ ] g e n = d b . g e t _ m a n y ( ' x ' , s t a r t = s t a r t , e n d = e n d , l i m i t = - 1 ) f o r c u r r i n g e n : l . a p p e n d ( c u r r [ ' v a l u e ' ] ) r e t u r n s u m ( l ) / l e n ( l ) -
Jak jej używać ? I to wszystko p r i
n t d b . r u n ( ' x ' , ' a v g ' , s t a r t = 1 0 , e n d = 3 0 ) -
Tylko HashIndex ? Moment... HashIndex nie zachowuje kolejności... c l
a s s S I n d e x ( T r e e B a s e d I n d e x ) : d e f _ _ i n i t _ _ ( s e l f , * a r g s , * * k w a r g s ) : k w a r g s [ ' k e y _ f o r m a t ' ] = ' I ' s u p e r ( S I n d e x , s e l f ) . _ _ i n i t _ _ ( * a r g s , * * k w a r g s ) d e f m a k e _ k e y _ v a l u e ( s e l f , d a t a ) : a _ v a l = d a t a . g e t ( " x " ) i f a _ v a l i s n o t N o n e : r e t u r n a _ v a l , N o n e r e t u r n N o n e d e f m a k e _ k e y ( s e l f , k e y ) : r e t u r n k e y -
Znowu uproszczony n a m e : t r e
e t y p e : T r e e B a s e d I n d e x k e y _ f o r m a t : I m a k e _ k e y _ v a l u e : x , N o n e -
Użycie d b = D a t a b a
s e ( ' / t m p / f ' ) d b . c r e a t e ( ) d b . a d d _ i n d e x ( s 3 ) f o r x i n x r a n g e ( 1 0 ) : d b . i n s e r t ( d i c t ( x = x , t = ' t 1 ' ) ) f o r c u r r i n d b . a l l ( ' t r e e ' ) : p r i n t c u r r # Y a Y s o r t e d d a t a ! -
Infix/suffix/prefix search n a m e : i n f
i x t y p e : M u l t i T r e e B a s e d I n d e x k e y _ f o r m a t : 5 s m a k e _ k e y _ v a l u e : i n f i x ( a , 0 , 2 0 , 5 ) , N o n e m a k e _ k e y : f i x _ r ( k e y , 5 ) http://goo.gl/7b3ZM -
Sharding Więcej c l a s s C u s
t o m I d S h a r d e d ( S h a r d e d U n i q u e H a s h I n d e x ) : c u s t o m _ h e a d e r = ' f r o m C o d e r n i t y D B . s h a r d e d _ h a s h i m p o r t S h a r d e d U n i q u e H a s h I n d e x ' d e f _ _ i n i t _ _ ( s e l f , * a r g s , * * k w a r g s ) : k w a r g s [ ' s h _ n u m s ' ] = 1 0 s u p e r ( C u s t o m I d S h a r d e d , s e l f ) . _ _ i n i t _ _ ( * a r g s , * * k w a r g s ) y = ' y ' * 1 5 0 0 d b = D a t a b a s e ( ' / t m p / s h a r d ' ) d b . c r e a t e ( w i t h _ i d _ i n d e x = F a l s e ) d b . a d d _ i n d e x ( C u s t o m I d S h a r d e d ( d b . p a t h , ' i d ' ) ) f o r x i n x r a n g e ( 1 0 * * 8 ) : d b . i n s e r t ( { ' x ' : x , ' y ' : y } ) http://goo.gl/nvRfJ -
CodernityDB-PyClient To jest jedyna różnica. p i g m e
j @ l a p / t m p % d i f f d b _ p y . p y d b _ p y c . p y 3 a 4 , 6 > f r o m C o d e r n i t y D B P y C l i e n t i m p o r t c l i e n t > c l i e n t . s e t u p ( ) > -
CodernityDB-HTTP Serwer HTTP CodernityDB Wbudowany interfejs, w całości po stronie
przeglądarki (client side js) Demo ? -
Dziękuję za uwagę “ Nothing is impossible, it's just require
to write "some" python. ” Codernity Labs CodernityDB