From 5f19876f7a53408f87cab90088fd30c1376cf22c Mon Sep 17 00:00:00 2001 From: jorenchik Date: Mon, 6 May 2024 22:11:48 +0300 Subject: [PATCH 1/8] minor fixes --- main.typ | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/main.typ b/main.typ index e34b84f..2c8fae8 100644 --- a/main.typ +++ b/main.typ @@ -89,9 +89,9 @@ Simplified version (to get the idea) for each tuple tr in r: (for each tuple ts in s: test pair (tr, ts)) ``` -// TODO: Add seek information Block transfer cost: $n_r ∗ b_s + b_r$ block transfers would be required, -where $b_r$ -- blocks in relation$r$, same for $s$. +where $b_r$ -- blocks in relation $r$, same for $s$. Seek count depends +on how many buffers are available. == Block-nested join @@ -281,7 +281,8 @@ The concept of conflict equivalence leads to the concept of conflict serializability. We say that a schedule $S$ is *conflict serializable* if it is conflict equivalent to a serial schedule. -=== Serializability graph +// TODO: rename to precedence +=== Precedence graph Simple and efficient method for determining the conflict seriazability of a schedule. Consider a schedule $S$. We construct a directed @@ -313,6 +314,14 @@ schedule for a set of transactions that follows the rules of the locking protoco that a locking protocol ensures conflict serializability if and only if all legal schedules are *conflict serializable*; in other words, for all legal schedules the associated →relation is acyclic. +\ *Recoverable* schedule is one where, for each pair of transactions $T_i$ and +$T_j$ such that $T_j$ reads a data item previously written by $T_i$, the commit +operation of $T_i$ appears before the commit operation of $T_j$. +\ *Cascadeless* schedule is one where, for each pair of transactions $T_i$ and +$T_j$ such that $T_j$ reads a data item previously written by $T_i$, the commit +operation of $T_i$ appears before the read operation of $T_j$. +Every cascadeless schedule is also recoverable. + === Lock-based From 226bf240d653b734baf0a1cad72219106a5a46ba Mon Sep 17 00:00:00 2001 From: jorenchik Date: Mon, 6 May 2024 22:59:26 +0300 Subject: [PATCH 2/8] fix seeks --- main.typ | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/main.typ b/main.typ index 2c8fae8..324b53f 100644 --- a/main.typ +++ b/main.typ @@ -90,8 +90,9 @@ for each tuple tr in r: (for each tuple ts in s: test pair (tr, ts)) ``` Block transfer cost: $n_r ∗ b_s + b_r$ block transfers would be required, -where $b_r$ -- blocks in relation $r$, same for $s$. Seek count depends -on how many buffers are available. +where $b_r$ -- blocks in relation $r$, same for $s$. Each scan of the inner +relation requires one seek, and the scan of the outer relation requires one +seek per block, leading to a total of $2 ∗b_r$ seeks. == Block-nested join From a9bb553cf3d4052f4f2d1f705099c789b02e3743 Mon Sep 17 00:00:00 2001 From: jorenchik Date: Mon, 6 May 2024 22:59:41 +0300 Subject: [PATCH 3/8] export --- export/DB2Cheatsheet.pdf | Bin 265449 -> 265910 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/export/DB2Cheatsheet.pdf b/export/DB2Cheatsheet.pdf index c4eb8d2512bbff54ecf1dcbe555e8432bf95c92b..5265743830c8a748a0c4c274c68cab33fe790d06 100644 GIT binary patch delta 21426 zcmV(?K-a(NnGm*}5P*aMgaWh!A*BN`H8_)TUL}7$X>S}imf!s=ghetF%{UD2126>0 zl4aS}SS`txY^P>{*%^3%#U_hQf?e#tpU3JJSuCDa)h)@661cn7UBx0F-+htnVfg=h z0xy~qqz%Dh@9#f7`JX4G|Ap)kg)mmey~B?`{6mU={_?l~-~0QoPw?KafB*T(4<~Rx z5_^B|K0o>4<*#_}pT9nN{%$iwKe#|#Qz_-%yPux?_+5uFerjKcefgvN^AGl=>wlK} zf8Bfc`pJuTPc9OZVH9D5g%pM9lqN$YCPLDFHqS7o0&AnNKBVye9BX|7?=KGg3{sCE zdlJ#yLvAO^C1Q*S?bp3t-m!f-u`h4>FEM{+_Wgx@IkPV}!>{{qE{5M67w%fQ3$BJ& z^-sIBFYo)8{XK;=p<=I}(5Zd7?r+-P`(7f=gkfs)E$RZXRupL!8SXYAb|> z_q+^A;5eG#h_+AMcOOzui>C7?9RK#WmHXPSk|Shb z__7Od`?NA^|@a~dJYj~)fX zl}2hrjyK$dD0BPuhB2;r#2kNe&umw`%&Cj|m|z5J#O#K{e&`Cg9#82aAr-w%L6IVs zYg+-9lv^B8#s_9Yih+1e>q+3c2C|<&b^&T%`;}gYU|L1vy>dJLK3=bTOa}fD=MNEh zk>JcD#6YB$MLHEoa;8E57=!*>2g;N{OCdw694CSxq8Mko0^nuFM!Ok8ZeU`?{L`=cV?mq9=n$77&5f{?78O87kTOheG3n6raNx|2ua>lpYYWhVgZd5Cfu*m{1jP{QweD8lR?jikLU=2bDzW37; z2F3-)+V?Cz^J!e|I^rOger2t+E3ib;fc=^U+zXgPs55$1_EVcky(rL*02V}q!Sa!Ic1}A< z-GLwhR}&T7hS`6y2>ckuT@hS^>sycn4pCZkL=z2Q1V7FM4K~5WTg4s0NGoOi9c6Ks zRIy;50$h)IFr{vz6cjVbaRoFLA_bk2+EHkhNZ)ozO=h5vcO@O@W5|O(jCjoFF*~&H zKZHW^)fSo89kL$+g2QkucffuKT&jWCTiFjqS_85)vLAoX7KV2{H)U#vZI=-D3GV8d z*313!!{Av|!|h5EBDc)z7yyhh3B1k#F9IXQeUs;P;1|X~5_GDfKsamje(Yi?Fi znF91QHW(Z`H$=A^iF91U!1KmMruY7J7sxTc`|wC%tR;h4I&QdfvwK^>viI()i|}!` z7mR%B-l5#){KLz<^+iqyB9wxt6kM2*(pT{5Z)kr!v0(tw??HJ3FR3DCNJE`-E&c2r zK4*!E2cgN75=$`#{>fBHhs7G}&4Qj``9dEw60Ftym}D#*Vq{UKA{Skt?|lz2rC4D` z)*#4omm2;hS?uR#Yt!zm)>I{yW2rf1AKn5$BSQK++M#TU!c!pL+v)S*TIA1NHk^~; z_C9~zB$bqK>3;|*>84BarP(|%Kkqrg#grJ2oXt$uxd8!7o20gNh$eP3TW}=dmT8GQ zwF57XmL~a9_w%Rp)p2a~)(N`GLG?7ffY8z0s>N!KgjSKs+MvX0V~vtfQrDGOBfuCL zIUpwMutp=38KhaC`kZ2TYjw|&RwlXZCUt-7vBQs-4G6Y!gZW$HjIJiO)2w7(xoKv- zp!t<$Jn8*6f3Yt<(is43rYpaRQ;hWnpDdP4FH&#=w}z%hV6w}0woy_w3mD_|)mCBz z_XHJ&EHm(^K`b*!3Skm}VhRaPv3YdT-dBJF>^7qfo8`9fPzNsqc)W;uj8r`!Z~K3G zA3yIm``Z<;YDw)bF5wE+^=?O*$`xwrgF%FgD4;Ygq-?-JDFv>0>EcA{PYK1jE2zfT zx58m~VKT<=MD%4Sp(+wKmp_+tECrJCRdFJfC&Q{lT1#nEWNL`3$DWcReofLl}n7$d41vEyO1=nnrKLApZ?sI^0M9Lz%#cTI;|ta{3`9ubzhxn8kQWGNMp>e5fV&4# zO*P?*^bG>GBT%*`NtKEeP@E7B$RY@RDgW*|39tC#-C3Tfn2S0yS6Bz;p zu6L|lRdlzU_QrsmwGgzyoyq_cF_&_QJN39xNgFt%vfl4w2i}qQyHZh^(U2#l@s>Sb zKCgF>-k+Y?cIFW;a#iC$Ko3MiE zGKmeC&~fBE5hLbcZ)i-2x~=G~Am}*s`$tD8qnf>uXJukYeUxq49xrFiy4_7RTs}Q= znh%JFclFN_4g`(*OM_Hs3S=#EfXxqu7d5M_PmF;ROz8%-3cO$x{H}jQ-)orqLl=nH z*+J=7>5cr9R6gbj9&jlO0y^ts)Z)vPJOsm|Avn7%W};5 zaQME>MD$gwzH5Q+5aSba+j4iNah7QdT7}Sf-7>4#>RGvGmAfc(QI^Gp`?PYP3B*cb ztv&;BZGwmBur9n$q|kqbc7iQluf|yV*Z~9&22%K&{k@UOkxjMmu=N1BPJ=BJxHIkV zE^thgcg#=A7X#18_0G>UQw1_=>M$2$8*nX;#Uq_JkxFU^aCS1QA_v zPD|H}k^A{$&fJf6&r*NRSnf27xFr1)+g+_WWZd{^o=_PIkCEfB2gE8|X^Gc_47k(* z^sGh#%@ru6MUPaTI4k{AIOhB5?!cWFUe@jB!4%xJ&w8>B$X2j}35NcDCEsV$ju#w* zFxsH|VvK*4mGanv&2c+Qa}yH+-hBfKcVb>80iyQzY$FKjXEnx|R_S5;nrSSBNKGLS z9~&)aYna?ngnZpXoo!y9=1}!WXBg={U4!B}5C1(PRoWD0=G|g8)mjo3J3f!}$ZECc z-SESQ)hqfY0jNyx%tfN_b@&{Q^8;^D#liO?-m!lf`_rx`CexK2TV@jCHPp8Up4Oqg zS8Mx1p+DIdYF~QB^%Q`>6e8FILD`p{x7tP2y0;7P$762P95)do8&?q7^lP_0iz$dS zh+tu2M6c7Xokxf8?|AcX)9Kjg&ELIaX@)aN3Z$Y0Z%+_SNYcYJmpXAZyz+bZ^{AI- zE&YF$BSndp@qCN6%f*bvoHsA#FQdf_f2%ZUp6b0SJ*w_xt@?5%sEgie&oqqmF6WpH zH#e2NbR&(Vb=S)A;|)kT%#z-gmKM$4=|1XL9N1B(Z7E>FnjX4PxHXulQ}#&bNhee zH?W+BP7Sh60%+pB`AsLK4tnr~a=|Gthph}ARno@U5q?n>orSB${yMfdw<2-fq8gYxagKi~_O_`cA z^ZvjJl3w;81HU+iQb=-e@XVTkwmE+|w$3WI_%%nbHOvrN5IJiCh9aQ|W2u{cABnXB zRp#`VBVo;i8`~mNs zNEI3x3)p!?K?pLOOPxf_u|itrHy}E}!cubQ42Od3RYIh3IjPf3gs45;3gXJ=P-lnUEmiyO+Oz;Pxf78&Z0 z%RSnjZ_jU}l+*0i4ZLNQ{@b=ilOnsP1qt?wU^Kb#u|HwzW`ZeAj50InKuJV2&uD2i zU7aX{h{BA{6v0G;%ZO8%kqAUp?$*ergUm!@Ll7ZiF8v!@exq1TyG?(pRkmzhF+nT$ zrn5Pj0nTNMmzwK5zI7}%mnat`jrjyI?+Wo=rr6z+jLu)*C5rIN z6&3(v3K0t>eGR)hXlw+aAY!ZqQ1`e-VOY>TXoN*UMWKT0+3OnhC@8H9o@JYQge%jn zD+3dqa?F%0cX1eW-4K7afuoW4wlr0#p|_o<82A+PXO8TK3_=%fB6r-UGq#*T&^3qF zN7;Z$i3;y? zr}P!0R?Us0I7msVbgCQ4gno@&g8<>l9zKbh{C?)E2rUzy>*jxDfLTSAFsW6r=2d`u zjc8D!i!D|9_wU>?GLe*wyMKFusCj6y73zLZbWyk$@RbUVvW<^k7GNICF?G;dK5Kt$BF@Fojk_IHyGktT__3ul zuDD?Q)P1_mk1l6WwJBZ~)6geVEb=~Q$HsXeTg}pn)3!r3q|wOrhe4Ngl!jQklO3Ev z_*QGrSTEdj`Yp^@^Y6>JJnF9SHrnp&=|r*KnL&?Hj!Tt#J{F)>Owb%zhO2N+ClP|Q zwwA*gMsj~0B9UKtDjzZc$$c>55RLuAQy|Uo#Zh*Bq9S(W%gNMiB}?cdFqiUYFWeGu zqWgS8zdsVWPUXdHFMIwm(^@|!dp#z5JtliSCVM?5d$rD^n7}pA#NA}xmJ_aamag^f zXp5GmYfWWxYsG9fqpEY7hn{Y=JY%YmoV9=k3k-j<&Rt9SR+DJZKZZ(|% z31NuCM$F83C?rhv1XxRX0!I_;8~x3CdMRV7fdUBwEzp1yac0s|A?4|McD_?UgBO8# zgRL@}1N+T;iZct@0euQ&vg~UN0jYjiP>@y`4Cj{tz<(hn1Y_kXo}*o zB^!UbtjBK`8w?11+RQj#muxsYUBopRai*lI3xNd_;F?7K2sCUK66*|JUE zVLR0daC7X8dF)a;x8y^%OXubJ&?Q+uFCn^|m|RUrW{5FK`J9aCLN0TAMzo+7E0tQF z5iM=t*zn!g77+;8Qz|6eNlJ7fEx8U&2&jJoB6B@2CAyT-+>#QVPfM;RL>rDse^SA` zgy=#_a{~*Ym?11OdFZu_Xo)Zv=~|I$Ml@FvqzNVTcbyWwy(E){)M3q(Zp?`W9SKt= z_P)ZDXwV+0O%8vk`LDnRwbD$AV#;R%8G!>TgQXM?c4@ZsgA*#{mz~;c6%Wh|ri*`4 zdqLjV;{r9kuhd>5LEvgd7Nz!r36HSh=`$fok^-FsFjn=DYE~{9V9Gk@%)X2Mb2;BE zem)=?m?ToqJt7E)VkB<-F*i4if%S$NCpvT3&+r*RYS^kaqu*uYs5r~RN5NZ?Vyd}B zr6i77EsrJy_SbEYd_*~j?O%5Rb7+6cnaK1`p4OD8Z~|8OWWgEfQc0w5K0Rb~MCY6I zP9>TV=5lg<=DDA0s?XwiX2?<6{Y41iOg_|v%&%$GP{q#1u3RfO*o|A{o5Iqr-1Skr zuId3?<73Nm&7D_?t)JezD%EXiN#FZYI#7lZx4=gRqN$vgO|6k`Exp9ya2|iT%lWAZ ztZ!ga%^C@)HCPCfJio3Ra=F<0o76_E8D_?M=_sg+i3!bN(b*FuHh9-umc>AQ*Gif+ zq(aWT3aK@jsU6|m$ohWi7P}f=H9w(pTs~G%$!PyuNoZ|{A2bj;lU<#tx00%Q7uB-~ z5VW1q(WONQE|;YxPUni2y$pY($-Ji-CpFIAj*4;HCc)Q|IFbcL4}wtO#bkQMvAz$% zomKSufW^+41=#(2v@&iVff!h?T2yOfF4z`s-~Y)=#`)VJx0`WP+zf*l0hCa!A_ig*NJ<5<(Ju)z^aRWRUn$d# zm;nJ%5V-nlK#sJ$W=4M_qp3Y=J|n*tvdc>RRM`Gwb&fN%bRv20|kAaX*bDQK^<`XAX!7;&yrY>9mF&%e(7WHKRF>iuin= zdvrZ_c)km9eV1su+tE&9kb-|AM0x7g71v;H*@L^~oo}KKPpE&d!@Mt8Z8gTB zs{~+k@gpy|f+0R6W)g(TGlv`Q_(bPZ_jM^pu1a>^i2XPzTQlb-4dz03^MsC`Owx@1O_&_niVrJ_0pB-+*M@G-h+NR0|1~nB^v$jj;SARVT+a*7i zKiSi>ypn;`C0NxuziZ`YwQ|#__Gnymz`OUs)w>q9g1bp!TGStNp~7?7{pMwUd>rj~ z%$6L9c#c`D=%(oxi!;oxa*)oX4rJPMW^#vrUxQ z?!sK6doE(*AL~_Yq;Bz;n401Yol!*Bd z3VUa?=JR$Xs5VJ%M5Qn|o!p(+x?jqD1Cf6b(j=3yh85Y#JYW|2BX3 z*V^Ct<{ta~(cqnK?va~o;cssIGx~pbxK`-RI47IuNIw_*w;i9$!F-N3^BX*?zvg7q zg5=2GYab(SpL28&*{TzcvGe3~nr@KdI-jNeo$tj=uih1h?s$bV5u zZ>Pehx7!BFTawtVU1_K?;Mx}~QS9(rSwGSY0g=d*+CPY747NZU%c=RTK{CS%nP7U9 zCocflY#HTho3k~WatTHzG3{qH-B~Ic7h(R{=|`^}hx<22FYg@e~7C0o%3_U2` z#lb^hdqPGV@bgf*Rm?|5ZJU2X%xg`JvdI_{#ENWFYQRY(=I|bx_H-F%X;Kj} z$C}-}ifA1Hwv+l~6%nEal&E$MQQMMU@f9nGdWwRGm6S77M5z;c!xnYKl(VI(BoZT2 z+RP*^5$tj$bWKT2hE#tfgz1=^a0IwdRgCMA?z-_$u_v+w*usvBd0k|B=<(?>g&Oq; zLKc?KYeejE&2#N5YJE6lLdP228xiFG8WrpI3VL`lEfQ0@qX1z-vu21Gdz!1FY(8Fz ziFh?JxB_IBkE~>j4-9S~VvnaOcKumrb_DwL+^j+G?f=l>ZFhfV2}VpQs!Aa+sb;o? z=z+p^&l~FPI5vTZMKosxDp=IB849;2F&fp_ki(u604no*JN4^o)&hzUQdUguJvM8B z$TDap2I%rDMGl1w(_BxLPlVVeb67MBD9S;pqjOERS=?>+5{e38k%Ne=q1@d1tCnV@ zB+w+G4*&zzoZieoC&yDFad1lpGuZ$C<(yT9&!%*_ZjcO;`pPO>Ml@Slje5S?y zG_5ElxHFqi8@75JsePMGs-0R_C|_<~2q+u?D0^H(uJ=Q(WA5d6x=TtEq7h0t@*B>O zsJ2{%Se0Uv)PGN^Sj!X^nqzM$*#Pwf4D zGQ!C^X~JF0{rMt}KfDXr5EW9qxA22qd0FbA9+-)eudq zUdm=C2fKgJT;5kIS7_;u0A6CkI8!s&o9B`7AgR4?DJ_~K*As1e7)9`bGkMpFOQx6O z+i0P8!3=j)j#j0k8khVOl1?VvJc@MZ$|_SLbmW^a!t+_ENZ1U@7G@gPqfFq#R*dzwxoux{9d zJv!KEh(UM?_1AhJtwMxo>iQe9r75`cd3c3a0WQLA8ma4DtVG61T7C#$oO3!DB4Opc z$t-_34xyJ+o$=Fa#%fH;MIUQ7q}e-Z*5%jfQ`L$|a-IrD1@EWP7Vc`!%?-vLgkpM? zyLpc0HM}6NA$YjPJ*T&!CIq{jId09*_c(%QOcj0~Jl>s!>lr^j)(RdwJyjj#5KBZ< zQ{p;3AyMk}#5I+25Exmj=l#bY?8`SW7m9z31_N?Em7ecDb-?NUY~Q%ct>15dk3swz z``P=S|Kvyi);;Z;@_IBwOmZb=wXOnV_~^yDP1PYk*y9FiY;#({fa!Z$nZxzb#O4V8 z5q~tXJ*xPS`QHyovB#A%3<(=d%oz6+X&d9{Qwf`l{J|qIqSWT)&xw8?AEwF~V6J~0 zQycmwSn}IZOF=jc_keN99HKC4_8W8ADQq7$)-^$>vXAIvc=$O!Xbk~!n5ZDZ6d*wU z;;`Z`m$p`Z!Nd)+Xv4=7KR&7D3Bmpln#z?bC$|udB<17umctk2fH{TTWL!*+m{Vnw zJ>w#E%)d!sA%lwu=kzuQV;bt!Hh6!7kU=rXgpCr&U_#`mT4Ic01*!qS<55isk%MB3 z0W}hP5E{HA;4(Z9ioV#2&Ibid1+yivuq8`E=w_q^qnL9gr{b(V7)}^I5oOoi_oiYj z!w}3Ta=cB$Jei9M_XSl7Vsc~lE1K9Z#GTbL4*W<4k7RHMWRSc`*zQ)GvL=6S&k2%- zQr=oj@et5_u(iK?G#`-s@0r`fD&dos6{9f4>_LZ9d^)!$noZDZr3lm7o~zdSPz_2g z6$@BBtW*hRnuvfQV{B0{g5{NqV8{|UaK#q^f*3Y|&x1`dsu>U0pTT5f*xsZTQVb@q zDQ^KZlZewV3eL>bGEzAZze#^pOjPpxfe;B+(-@5qwqTGB-RVplcB5Y;$IR2 z%mbI7$^*CqIX5wrab6{tf6D_4e~Ka|)~N5p#bOmm00b$>1V9lyJW0xNO8#V4Vyje@ z{QA5-J3Bo+efKP|3wrG$AneZ3$9q2S(f9o26{L7OcUi}@N{N?XYUi|z7Z|}#tQ%Y-ke?oAFl#*PX z{QTD^fBddT2=$1_@i%_@Zzn&$d2;^qlm8j-#V15|gfb$;36>o~QV#oAU@3tSG!}D|} z1s7y|+@*Kd@Wkuk>gg>vf04nwn&16-x_lVkkMr-ooyPNiy5Mpe^;LMZ?}qE2p2$w& z?Rak^gZSvKjk6f`$1$ijMcA#r>(NVgy5AVmX8tr?W?d zZlfI|7_;_~8y**gEk=HJQ9g3rF)TO>Ec%ye(Qm@rB|3>2BVB*-hepfBW5k1b#%MKb1f(l$bwD z$Y-{TuH4U&&!`PR0x%w=?2O#vokpOfhOOROH@?VCj9qmC0gcQjfW=Fi7PkZh7RBzY zYnTS4Edgt6G3~ijnXxn2e*~sx)EZJCSPS+8w1KgWVBKJp^%4icauQBt%Z6-qF9<8b zBnxPg8%J6(f5bYbg;p(;)*z^sOa5D_AP1cTwt-ku3d<>GLO4>MoQtS7MnDh?snkKJ zHao6Ki{TCMy0h|9UEr=yC`e>k87gfwA_9Syy?f5yPs&=i0H zv|kIaVO)B#7;2WnPstIs^HO*=(x~r{f|{rwaaymI=_| z$=@f;-80wZzm3397Pqk$`X|?F@B0G4gu!+Qq#E|81e+k>USrk1tD@5iRAH-h!?@$1 z&r<|He!$>oF4yDq2(Av|3nbne-$LtV&iG z@CG0m+|aDA2Sg$Scs>-o8F1aoW`c~{vw7@)e|~yeIw%+o*T$>SN|OdhPjwi;V1xc3 zVfZTK=w${^0D&S@tXW!cPmmt5fi}JbqgP|DlvvV)O49`Iu*L&7Qx#hOIm`l_jK{zN zwXRey?t(a{Yg}-MArVPgLqLH6#>TNT1lRqJ1YnQ`^rU^@8a#Mo#4QJ|pQj}Wr{JT~ ze}!l#a}PgslK{%WtnMa(Isw7C6-vaA4Q&>-0%ETaBvPf(8VE-ar0JflpJF>f0bs?s zabL2`1gCc-zL02Zfb zxdME7TE${TNns%M5f1!ya znl!b$HZ7>ld`r)BTdItWO_zKcv0EU{)p4OYY@$iZX^6!+>S~?%`9bzTvgQXo`^5PqBC2b?CD#?>Goglf@f zl~wp`M0X&Khkf9w>j5NRdk2S^Aq*a?RirSP;UOiLs|7qGz;6LPH{ z3uGutSmVcQ+waR$zR1Z5*dIK)$`u+JUI%EMYS%izuS{vGR_J8IyNZZ4I@$29Mhche zWUv9iTbGib9F?+3{UjYY=^!SKI{B!RAG1y-5P87TWYiofxkzgq7A60-e}78Of*l4Z z22JajQnU!`09+b&nX+=MV|ebe%4Nz&-Y4`iP8cO@NI?N@cLBWs!8aL1)#IYLeM}sYb{p<_??8me{2B-=L+q-?(p!yLI z8C#4yF9@_ToNCQS2=ieie^!}~U@^nA`{JpXvNWd z91;-7@4I0?{MN(HaO+C=fOHek?x+&6vPLbtwOLk5aRV#;RZWNT7_XN7J_$# zVikbb>hqiwC?CLnnhDgUs~9a+?&&B^-7UQ+r(cjWCNS8XAj>-@6{FG}!Q6~;febKX zlxj0MYo-M^!vEIje`Q3+#3Yw)(u4}L<4A}~j1MFPCrGRayFrMUml_`paLf^Q^# zBgO}qDwb3f$K4DTK&dXSf&0oaKJY$4xHJL!M`!HOI%C=79?*T1>BYMuJ8lvxwYm1V z>kYe}%g$nExJ(9=LZ-h4gdst;u8{8>f^v-D74n@!oDqZ(f2mbyT$*r~AWND}Bg+Ez zhH~(L+O-LQQv&P+QS9;qT4`_w-Qx0Bq@m|n5RgC(SMHMmE3%CbiUAeNrAGpM&!kqh z3}}2&u2-R8x)YQKP_W-BP%s8Y9;;HRV14g>7~pK-OPx~coB&BoNEnrMCCv#Q)I2AhQ_K5z=0In?E)B7kX_`k>mo z%oxFaT`u4m4=_40VRqeS5o}7DnA&@d zQPh|iTWCrJfpvx*TY_wDiL%(dWTtZ(Ew?Fb8G_Ti?Bl_h8k>%qfp%^E4jMTGADgjB zlu-!0L7qL1Mh;k+!h%BWNKBg<#SdK!wl{L9S`CKbJ>bxvd{vzsFn}8d#XI~G%__rA z!e&v4e;Ry?$I;56igF=l2Z#~U2Tr-|d<+;Ft2K0CA{3$8yA(iL0*PvZ!9#1mHH`)U zbYbS!Rt5rC98syXEHtZ3a|A{4p}VoW7XFddUvR*zZuM;1fD`>>GYz$v%6jStZfG9K#Nf4y4)SI?E6jlLNyl0r&`eX}yWR}qtb zpbLGoO;>Bj)47{IX)YNbK6&TgXdSh)+#{+|uP>+TrV)5uxkFyq`}r-AZr2GP70df_ zO5G<%ykNUgqf@;}FdtX$%SStkz|?Q15nS$Q=SmKAAf{Ud2#qFfemu*eI;I~!%OM+7 zf5awatk)dnAi!wbK*gUBVtMmDIoie@E?d)GkNu@^IP(ztE?-3XVs75FMxss)R(e zP`@yWJBdhJGR0909fE#|; zw?J+}=v3`>E#Ce?QWbVK*-RTdERab*k!&Y@S-kcMyXjIDxPDu_TPx&vhqO6bxmn1m zPEvx_2)S)%>Q1rr9ZQnm0>ejR=tgbO|4WiHIHp5wJ&-kJp+4YI9U(cY?8!o4A&8c8al%D3m~Xm~ z?y6U9c*XqF?J{iz{!zqH4OfT6Q6XEyt(Yy4t%Am40B{+zf`uB3%?uK^e=cJ*YOs+E z3~kEeFN{yj<9oKAH&%_c=~gwpXbw${yX>UXXyb^0s|6~O#?~|2ed8b z+nxGbGNO5f^|NE!LvP3dcF?ToF z6WcQUrSW2ojqP{8oBt6>e|!9X{>R14O8N46vRf{^Cl4RLju=s%1?G-8TO7DPYjX3P zbNAgdlmsPHu}w=>E;R{k(rBFidTYlM%Le`6tD*1Z1BNk(f8gAUa({i+c{`26 zma2XTuclACuM>-W=iPGUQiLUyk7?TQo^j_*sb)vPt^vr7$iOOoo`y8rqtfl6QUa92 z2j4$QnysD`!ShG;Pp9u4C(oBke{|{eoxAPJhU1PbJ(>Rzk^pBj62tTbi(Do9x z{Gk6OM6BQ6(<`6Bf8Q_RA4TF!55Ez`pkE36lbgR88-I)ObBs>;Dg6C%{0y$c=bLND z%kei#8ezypda%Y4&j?@-YZoNu#$_W_%d`1yuH$@jt+|dV`25B5gC~&#p6i2cDNb8` z0?c2~L--!7O%tfr;BbN)`3yb)x8xMQ&=h{7&4ud1-gK(Qf4|4?rq96{IhE;2NP~@2 z^ekhZb+I2{&dUa2;aA?y>GRj01N7NjTYD*RexB&je|8o;bLG!QvK6}(N%tf+|4pcaIT@}vvo6r*v{ z9PdUXX_wjcR5124D3#X~cLZ+|P!dyr?S1kgzC2ZAzD6naN$$;>llGbIwCefDIpGU@ zXpWiHvc(&vTgQ@aJka4c8GpZ=J~JM((tLC6f8cPQ!#|O9Fp25W#7%S2x_*blN?!LU zfYc?i-OK*VAE(v6N^Gn}tF6en&A4O>H?E(<-1bqH9ImH9+_?Ys#v`$`I%t#VMRI)p zBwwwp6uBWXou}{>QU>MpXH>O@Au{4uj2mPtO-*G7?=H2oOz4BD2P!zPv^N(Lp(@6BfXQtCi+SX2q7_LXS%WXhW&?q1J@&1cj6!c zQL~3K&KB~3m&k*IP>5fNP}m_oe+;cH6ruEC1OhV2VU!)FJP_sp4SY!A0KiW0^y$58 zg>_PapiW>@1u(x&ln4b=bWb!nN`<4Ta5NQmVk+!jGMIxB36(j~5OgpE={UleuE_$6 zKo@(2?V`S9aX)j^VKb6ebWWN|AQWdz8|Mrsb5Aoi;nw*A4j;yV9v7`#e{74N_HeHV zI%ejiQ$%F*8e%5Q#FZ)xqE3^%oo3(Pe~i2=+)>OlS)yLR5VpKxksao*NGV;-9#KwE zJA*H4>5MXyU1joEo0H0b&al9gSJ2sB2r3N~fpJVJm!v5SEH=rfAN^rd}_X5Jji4t5826^wCBxDr(;$#8-vZK<{{~TvI6s8 zbEOKwuxCh|&yE;QXIAizNGb*=Yl)|c)-5d0N#+6>R5V^V^Kqi3kM8RinQ1O_+8aW4 z-rX+f)Om5Mg%v3E$wzl)B_?e<9Vk=b)0|@Ia*LX_mhA>UMH=kJf57{CCO=&Jxhy8(tKQFnsC3zKmIUESc6nLW=}g%tHlIT3W3$VZ^=+No90@ePIc6E; znKHY@ulgkO4CMGOe{$QIy9@s2EG^T2EgfY^w;ewg)*+M@|O#ZZK(1^^9vIqe+^_dy?L})!Ab5jvYcf5 ziQP9(sZI$YL*rY)Qn}$DApf`;?T5%rW42o)@!TeCBzh8TZrZx+1uF7w-R{)c3IQ`~ za9-K8ELj+Vnoc?dVYMoo{LDoRyt?KA37A0!8PA^rmM9fGe$Rb&c9euX?MolDB1?-w zgzij7v``}tfBU{Smd;AWiZYG5CB`{8!n$6*S?#RUn`w@pVoh`$PP&Z%27j2I<0n+U z3&;tp0%K3S^;ps`PD$*PH`9Q|yPfW^8ITc;w~nGBnRAh%l}xVZE|O(aob=jV{bJ=5 zaUk9Y*5$5XhW?ZGNPrJpMYnfOyL73h45obeV#n%Me>c7ai2zke-zD-CKN~tI>b;ey zmMXrCTU&3g5f~PfLzpG7Xa`fih#8pu8q+X3OMPYFcM49yO(B?Wv9NRZCQyD7k?{K= zjEE4mf$fbY9gzuk^8&8WGca2>O{%1NVY&-Fj~LTg>pY^fGht9me|ekPfL`GHPTeP~ z&a3BFzi&7<4c3Z*9IEok_WZoFa_zo+qX`1>!h6yNUZH4NN zOzUsNxH`yXAjI6p<884jVn{oQ7`+RNfTb{WfBDTu$paSEJnwGAuqN{D!vIRCbr6At zrC98{eC8(Fe1Y*0Ef>XM(s-pK8P^?$;0o8!GHbbM^>&cU%n&u2KP?yErIyLokh-0W zTk~}v#inv3I?S1%2Pp#0nQd5do=c+**ngnKO@njMWdD6TEv~h*tYo!zuC>04yG0KT zf3B6#N6RiwrxR80+Op#?MRcG74E)-TQ?lByqd;Gp9A>c)R_3_5l$hR`WhczJ6Y?;{ z+E8;1xC=j;c3IPonOY}xkQ@u4wT^HctbKcQww-{$5|#2G7n&j5Da0{<9M)Y~s^mj# zD}!y7u(yY4+#$d+!2Qm5W9s858>}A&e<%aYJwS!O^Tm)g-5M;p(rWHqn`{;rwpkA` z;<^WrvbM~D8oY**w$|$xv&;j%>8`HFhIXe@^Sfjw0_b@N4-g`oOnotJ+gaK2I!ye- zxYpr_T?O0=6t(C(g`Cd#rW5}7-`n#cOjrD&!9N>1<|8gP|Gn*)KQ#W|bkm3He?zCZ zLG(u)C~BfaN0ro~wp#CYBIZyPR#l6$yGF{`B-~v`DC3pK|M{rzBnO8h6%5@gb7=GO zfr}i&%FLwVHhciIXiQjp$8ewqm;n!Y0l#>A>4%LXCMqxD7*>?&>^xackMBLr zag&n2J!;4sT|7II92!3QC*hbEf7j>1LUAgQ*Xd3b*XL1cy0w!`?}OMG?UgcmqyKFu z(YMp8+WehQ2|H~!QrZ+XBFvU&xIciLRvjLa$_`ObYiib%&^-uhhc6?AZk6=%waadT zO%rXlq>+na(M<#p3B&p^if-T6TjYlHRSsMvg(%TWqUKZ`-H9Q)wpl_me?U%DIPjEh zLBU{~DaKY@*O>H}k7oSPk9uj!4>EC6YHZE^&1dILnaXM3z#J|lO^=>3z2lTBEA?_b zHp`sSCZC@$AW~xKB3$3M5h2t#rr?(#X`0S_7Z8LM8p@T8Z(^n4S zm+jIOmwR#0uEwrU$j)!-^Of(Z_}1QCQB{~Xaa}-tdUAuu`#x5kb(tWUnW5J=4crBr z|9P6g`vgT<1>vi-AZJ!~hU(Xe$3CG3?TkK7ugj>8ayKWE_*@Ywv5pIst=f3}Zo+sS$+hW+K5c%;y9uHlj&DiCvm?Xt%DXW9L zoHN-;#{FA~D|$j9wfj!cJ^GHdS+hZyh^1ikyL3LzeEoC9NF&(&*m;k8AM};gYldL^ zUo%v!f9;>YarAa+7!*Ycrc1gpd^cpOHeIg7F5#sVabu|5Q$oVftR|^oXJcVtdoMLu zW;$h8G8g1rOP_a>_+XP&xr(!lf_rNuBDZBWE+y9L@RLSYLAX8SsjsBO%7>3FfQ*(n z!a>ucG=ggsc_!vNSHvv8lYPu*ggLziw@L*$`rMyUvq1g5m zd5}cN*%-T1-E$Og3Px?-T@sMRwc;?4E6X`6e*%7Nf{G-h_;deCtHgI(Tv zieZtrTVW~88+BCeT(&+gb_1c8LwnX?0 zb2TYv(L%HS1-bs*YicT2}Z_0>YK`2e=JZPDhm!o$^7Xu-bIuE zYjxtAo9;Pq?QkXAmkQlM;<%Wf)GTQ>KIK6s!qav4jH0+`ZLti7FVPu7>z8RR+B-}N zWO05T-i$O5u9h_`o(Tw*5F3)>T##z0YY!R)!FrjxZ9^08uZZNTTTFX;3e_0c_hq#s zDp~J(Ey~{PH%8&tiEJSIa|~X;U&I>TX=o=F8T8)D`9{bqgYYn2Y}hMQ5{mGj?>H6C zwTJiR2>d?fyyag@CmHV*^KFKU{4jKu{&p#9GYyBOlaA-;5Vu-v&ypUxd{p4XEb_tB zN8IM^tDN#5+Z^0L0~Vg#2|+3O{1o=PR9R@E#tu4804K3f3zd>(uPkMqnYlF z`EjSWzo?6MB)He^@rE1-Q;OW}IN&3_8J{DqxUIve#x{q!-(H=wsE(C7we!Z4^@*JR zh4TSYyFC46Q5~+NuP%>EtAtmTT%~CqrV#Ctvkt4LwzE4KWmBiDV+InR_D&Rs#=W%u zZN=+-Rq@t4!KaZ^+L!s2uWMEixI@d`L3tMS{@?Iii#$W`2C*)+v~Q|c_Cvq6X$SJ# z+pZO4t=}Clp8>_(E3@=4KW!|8V{a`R{pQi>u9txl!SYM(r@M z0{ITwTqGWxkj)J{#RGKp%xc$-kWQHW`KhOT)Oq_ffiB6wC;R@BVv3vTXp2r@yv(nz zEt|}_>+jR}QfOG8Q~?4}pcistQw&n5tP+kZVPd|}z-}FZAU2qJIeV1GndvL?&7!)Z zCdC7Xm5n)i4ap^nYg%$z?Wn_}=Pf}*ZtD9eR>yqm!9gvbw_T1D{P0$OCchT`^|e0I z7)V((Zux6mJNr(T6qV!hjCHiudgN@MRANcGj6T03bfC)5y0pFIt)ph{xAm`~6BE1L zSvy-3TWv`jk4i8xA5D~FgG+C&WXts6xOyGh=IcMTn~IV1H)#E;{ZT7(PIVOG@rT?C z%>ijjhs`j19ZC&H&E}9qwL${f==`LgBq{&JxYOejJ%woEI|rDVT0D7AlDCGLZb{<) zOTbI!W{c)VxID^ z+Z=yc7z&bpM(@@nw)6=LJzFv$X8Kuzo|qe_b#jDVT9HbTJ6lqlyXb0hxv6yibE=t& zM9{{_glBocs&=r~itY1sO5EN1n}b)a-%lm9J`a&$1)MJ?&+uQuc9!w1 zoMOA+`|&TnG`6nO0T% zF2pYdZ9_a*2@cdKGzs4WB$zKfwvBI9F%MFKL8k~J&MKj_4 zYBdd2d&ODOx2QYQz$^UrVG2?Eq2)q!N^>g5=e(tGULE{xF5JkhJNcE|3KXX|*Ujp^BB>>h_2 z^Zxo^;_dNlQOwoMQC-(Ii&n#K?J?s8wqA|8IGdyV3i@|6VK3@at~pA=d^bh1g)z1d+cJ9l1>{A3U~tXHxlI^ills?I1Z%%W_91I8BKIPRlVlh_}aDItm%@#=$UgVtT=m; z3XO51jfigInEBhmR_0{!k=6vnjbLYdUNB{h&QVTX;Tp$*MB;SWAQ2>B!N8F5?jZT{ zSWt_MX@RL5qOKu^yQ-Xdedmz{pd_l{!|HJH{_U+#eIiY&arcQ`icP1a8M6MN-_R@@JkYBQ?`V+OXqT~WR6rW5cSl{9r! zJ&K;=&lDYgrS4`-Db-Xa`!5leY8UWN7&d8^{oW+%W;$ycME6wQPN_OoR;XTx)mvZZ zpbW~H$B?@e^3+(WsG)9Y61WM0AZx+UV z1FLM!%2TQ7vblTijr^uI_AR{NIS`$`o49WKooudwgr`!4S-Oi#*H~Sf%Fat~v$M2& zR71{&%*uj_EnJFYG`sXe?s>$YmScD(3A-h}2c5Y}WmUg7$}ETB=6w52FytXsWF_;} zdvUf$t<0<5;gbzWKR`B1)1gjHTc`+TuT+Cgy4 zY0Wx8X{z;d72l!8?=Tmoyw6r5;q0#jkZqGUxZGZe2eHr&cZ6t|a7t!1shWOgm1!sLb``5CUpE+y5mIZ=T|Tva;er79XCDRz zD1!-)u3f38iDEebN6?Lq9T!UJIk4bKc3?v&%oW~tTjnwov6N{;+|I+;~qdx zl!yr~nArCq{|ygMeKK!atC-zOVULN(1uRvz$BHLg!}0vr%2dDWc}^?2%biid-bS3M zy0ZZVgyD2n9~0BnK4W%8HK?Q@FrLRdUgjyxp1v6Kfe%XkP<$w?w=%7C(*-5NQ0z*SLHEB+rUt{Ua-}+P;cYM zLAgR$1eTs%qKHFlmwH{G4R#wi8>aE(d$t0Ln@=Q0wsXW;PTq2lqL*)GTp1NQ)9Mrsn&uKqT>fwwb7Ju5td~_?a zLy-EMPJi+ytxQ7pEc4e3;L$W$7G_JvM@oa?vmnCq6^PeFDuzv`upZ509h1QiWr1k9^+W!5I1 z@2W`0lC>S{P1n9*X)!p~zYhuPSCguJc;zi`5&0;vOl6VJ-V!3)+`@ zzNMG(-*7(+__OQT424=b?4Cn?n&9)R%_CufJ;?Fjf#II<@O7MTi z?||lF>&lr5zEc~A3r>5UHa|_&uU^L}Mv{MDRsjbvmT&w5{01;Wz%VQV3MXyt00J4I zU<4Wghm-tv0Zxnv1Q>&aKuK%6fFec=9E^fsu%wJVfE^PG14hD7Fbs)zACSWUM}c8* zG^uePKwyMok8K2;ggF3|F=CDb7#M=Ia{xfG=(*!<@V0no8$3yo3Xoz#V8AFW9D*d_ zsel)ZXe1bkM8Zk?R6zVclb|73Qv4wxfe8fxqmdXaf`t7Ic)$od#-Xt&QuS|uCo>!a z10%60%(2`bKrka53r0Z^P*VLLfF~0K0Y)QWFeFL&2oTMLf`Q>k2o^>fJp#BfA<$qL z3IjvM>I0uJL6KlM6a~k|P6C~nA!slhhJ<2~Bz;<7I>WJng(FB*THxvbwabO*fZB9S zP^iB@6EK*X}bk+U`$g4Ca delta 20973 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 OZDOH}5)xV_+W!J5Xy%Rp From 928bd8554fb5320cdf9411b87618fe3bd19c16e9 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Mon, 6 May 2024 17:35:09 +0300 Subject: [PATCH 4/8] refactor: use columns --- main.typ | 358 +++++++++++++++++++++++++++---------------------------- 1 file changed, 179 insertions(+), 179 deletions(-) diff --git a/main.typ b/main.typ index 324b53f..a4a8da8 100644 --- a/main.typ +++ b/main.typ @@ -1,34 +1,34 @@ -#set page(margin: ( - top: 0.6cm, - bottom: 0.6cm, - right: 0.6cm, - left: 0.6cm, -)) +#import "@preview/tablex:0.0.8": tablex, rowspanx, colspanx +#set page(margin: 0.6cm, columns: 3) -#set text(6.2pt) +#set text(6pt) #show heading: it => { if it.level == 1 { - // pagebreak(weak: true) - text(8.5pt, upper(it)) - } else if it.level == 2 { - text(8pt, smallcaps(it)) + text(1em, upper(it)) } else { - text(8pt, smallcaps(it)) + text(1em, smallcaps(it)) } } - +#set enum(numbering: "1aiA.") = Indices == Bitmap -Each bit in a bitmap corresponds to a possible item or condition, with a bit -set to 1 indicating presence or true, and a bit set to 0 indicating absence or +Each bit in a bitmap corresponds to a possible item or condition, with a bit set +to 1 indicating presence or true, and a bit set to 0 indicating absence or false. -#figure( - image("img/bitmap.png", width: 30%) -) +#tablex( + stroke: 0.5pt, columns: 4, [record number], `ID`, `gender`, `income_level`, `0`, `76766`, `m`, `L1`, `1`, `22222`, `f`, `L2`, `2`, `12121`, `f`, `L1`, `3`, `15151`, `m`, `L4`, `4`, `58583`, `f`, `L3`, +) +#grid( + columns: 3, gutter: 2em, tablex( + stroke: 0.5pt, columns: 2, colspanx(2)[Bitmaps for `gender`], `m`, `10010`, `f`, `01101`, + ), tablex( + stroke: 0.5pt, columns: 2, colspanx(2)[Bitmaps for `income_level`], `L1`, `10010`, `L2`, `01000`, `L3`, `00001`, `L4`, `00010`, `L5`, `00000`, + ), +) == B+ tree @@ -38,32 +38,32 @@ logarithmic time. It is an extension of the B-tree and is extensively used in databases and filesystems for indexing. B+ tree is *Balanced*; Order (n): Defined such that each node (except root) can have at most $n$ children (pointers) and at least $⌈n/2⌉$ children; *Internal nodes hold* between -$⌈n/2⌉−1$ and $n−1$ keys (values); Leaf nodes hold between $⌈frac(n −1,2)⌉$ and +$⌈n/2⌉−1$ and $n−1$ keys (values); Leaf nodes hold between $⌈frac(n −1, 2)⌉$ and $n−1$ keys, but also store all data values corresponding to the keys; *Leaf Nodes Linked*: Leaf nodes are linked together, making range queries and sequential access very efficient. - *Insert (key, data)*: - - Insert key in the appropriate leaf node in sorted order; - - If the node overflows (more than $n−1$ keys), split it, add the middle - key to the parent, and adjust pointers; - + Leaf split: $1$ to $ceil(frac(n,2)) $ and $ceil(frac(n,2)) + 1 $ to - $n$ as two leafs. Promote the lowest from the 2nd one. - + Node split: $1$ to $ceil(frac(n+1, 2)) - 1 $ and $ceil(frac(n,2)) + 1$ to $n$. - $ceil(frac(n+1, 2))$ gets moved up. - - If a split propagates to the root and causes the root to overflow, split - the root and create a new root. Note: root can contain less than - $ceil(frac(n,2)) - 1$ keys. + - Insert key in the appropriate leaf node in sorted order; + - If the node overflows (more than $n−1$ keys), split it, add the middle key to + the parent, and adjust pointers; + + Leaf split: $1$ to $ceil(frac(n, 2)) $ and $ceil(frac(n, 2)) + 1 $ to + $n$ as two leafs. Promote the lowest from the 2nd one. + + Node split: $1$ to $ceil(frac(n+1, 2)) - 1 $ and $ceil(frac(n, 2)) + 1$ to $n$. + $ceil(frac(n+1, 2))$ gets moved up. + - If a split propagates to the root and causes the root to overflow, split the + root and create a new root. Note: root can contain less than + $ceil(frac(n, 2)) - 1$ keys. - *Delete (key)*: - - Remove the key from the leaf node. - - If the node underflows (fewer than $⌈n/2⌉−1$ keys), keys and pointers are - redistributed or nodes are merged to maintain minimum occupancy. - - Adjustments may propagate up to ensure all properties are maintained. + - Remove the key from the leaf node. + - If the node underflows (fewer than $⌈n/2⌉−1$ keys), keys and pointers are + redistributed or nodes are merged to maintain minimum occupancy. - + Adjustments may propagate up to ensure all properties are maintained. == Hash-index -*Hash indices* are a type of database index that uses a hash function to -compute the location (hash value) of data items for quick retrieval. They are +*Hash indices* are a type of database index that uses a hash function to compute +the location (hash value) of data items for quick retrieval. They are particularly efficient for equality searches that match exact values. *Hash Function*: A hash function takes a key (a data item's attribute used for @@ -73,18 +73,16 @@ position in the hash table where the corresponding record's pointer is stored. database. Each entry in the hash table corresponds to a potential hash value generated by the hash function. -= Algorithms - += Algorithms == Nested-loop join *Nested Loop Join*: A nested loop join is a database join operation where each tuple of the outer table is compared against every tuple of the inner table to -find all pairs of tuples which satisfy the join condition. This method is -simple but can be inefficient for large datasets due to its high computational -cost. +find all pairs of tuples which satisfy the join condition. This method is simple +but can be inefficient for large datasets due to its high computational cost. -```python +``` Simplified version (to get the idea) for each tuple tr in r: (for each tuple ts in s: test pair (tr, ts)) ``` @@ -96,51 +94,48 @@ seek per block, leading to a total of $2 ∗b_r$ seeks. == Block-nested join -*Block Nested Loop Join*: A block nested loop join is an optimized version of the -nested loop join that reads and holds a block of rows from the outer table in -memory and then loops through the inner table, reducing the number of disk +*Block Nested Loop Join*: A block nested loop join is an optimized version of +the nested loop join that reads and holds a block of rows from the outer table +in memory and then loops through the inner table, reducing the number of disk accesses and improving performance over a standard nested loop join, especially when indices are not available. - -```python +``` Simplified version (to get the idea) for each block Br of r: for each block Bs of s: for each tuple tr in r: (for each tuple ts in s: test pair (tr, ts)) ``` // TODO: Add seek information -Block transfer cost: $b_r ∗ b_s + b_r$, $b_r$ -- blocks in relation $r$, same +Block transfer cost: $b_r dot b_s + b_r$, $b_r$ -- blocks in relation $r$, same for $s$. == Merge join -*Merge Join*: A merge join is a database join operation where both the outer -and inner tables are first sorted on the join key, and then merged together by -sequentially scanning through both tables to find matching pairs. This method -is highly efficient when the tables are *already sorted* or can be *sorted +*Merge Join*: A merge join is a database join operation where both the outer and +inner tables are first sorted on the join key, and then merged together by +sequentially scanning through both tables to find matching pairs. This method is +highly efficient when the tables are *already sorted* or can be *sorted quickly*, minimizes random disk access. Merge-join method is efficient; the number of block transfers is equal to the sum of the number of blocks in both -files, $b_r + b_s$. -Assuming that $bb$ buffer blocks are allocated to each relation, the number of disk -seeks required would be $⌈b_r∕b_b⌉+ ⌈b_s∕b_b⌉$ disk seeks +files, $b_r + b_s$. Assuming that $b_b$ buffer blocks are allocated to each +relation, the number of disk seeks required would be $ceil(b_r/b_b) + ceil(b_s/b_b)$ disk +seeks -+ Sort Both Tables: If not already sorted, the outer table and the inner table - are sorted based on the join keys. -+ Merge: Once both tables are sorted, the algorithm performs a merging - operation similar to that used in merge sort: - + Begin with the first record of each table. - + Compare the join keys of the current records from both tables. - + If the keys match, join the records and move to the next record in both tables. - + If the join key of the outer table is smaller, move to the next record in - the outer table. - + If the join key of the inner table is smaller, move to the next record in - the inner table. - + Continue this process until all records in either table have been examined. ++ Sort Both Tables: If not already sorted, the outer table and the inner table are + sorted based on the join keys. ++ Merge: Once both tables are sorted, the algorithm performs a merging operation + similar to that used in merge sort: + + Begin with the first record of each table. + + Compare the join keys of the current records from both tables. + + If the keys match, join the records and move to the next record in both tables. + + If the join key of the outer table is smaller, move to the next record in the + outer table. + + If the join key of the inner table is smaller, move to the next record in the + inner table. + + Continue this process until all records in either table have been examined. + Output the Joined Rows; - - == Hash-join *Hash Join*: A hash join is a database join operation that builds an in-memory @@ -148,68 +143,67 @@ hash table using the join key from the smaller, often called the build table, and then probes this hash table using the join key from the larger, or probe table, to find matching pairs. This technique is very efficient for *large datasets* where *indexes are not present*, as it reduces the need for nested -loops. +loops. -- $h$ is a hash function mapping JoinAttrs values to ${0, 1, … , n_h}$, where - JoinAttrs denotes the common attributes of r and s used in the natural join. -- $r_0$, $r_1$, … , rnh denote partitions of r tuples, each initially empty. - Each tuple $t_r in r$ is put in partition $r_i$, where $i = h(t_r [#[JoinAttrs]])$. +- $h$ is a hash function mapping JoinAttrs values to ${0, 1, ... , n_h}$, where + JoinAttrs denotes the common attributes of $r$ and $s$ used in the natural join. +- $r_0, r_1, ..., r_n_h$ denote partitions of $r$ tuples, each initially empty. + Each tuple $t_r in r$ is put in partition $r_i$, where $i = h(t_r ["JoinAttrs"])$. - $s_0$, $s_1$, ..., $s_n_h$ denote partitions of s tuples, each initially empty. - Each tuple $t_s in s$ is put in partition $s_i$, where $i = h(t_s [#[JoinAttrs]])$. + Each tuple $t_s in s$ is put in partition $s_i$, where $i = h(t_s ["JoinAttrs"])$. Cost of block transfers: $3(b_r + b_s) + 4 n_h$. The hash join thus requires -$2(⌈b_r∕b_b⌉+⌈b_s∕b_b⌉)+ 2n_h$ seeks. +$2(ceil(b_r/b_b) + ceil(b_s/b_b))+ 2n_h$ seeks. $b_b$ blocks are allocated for the input buffer and each output buffer. + Build Phase: - + Choose the smaller table (to minimize memory usage) as the "build table." - + Create an in-memory hash table. For each record in the build table, - compute a hash on the join key and insert the record into the hash table - using this hash value as an index. + + Choose the smaller table (to minimize memory usage) as the "build table." + + Create an in-memory hash table. For each record in the build table, compute a + hash on the join key and insert the record into the hash table using this hash + value as an index. + Probe Phase: - + Take each record from the larger table, which is often referred to as the - "probe table." - + Compute the hash on the join key (same hash function used in the build - phase). - + Use this hash value to look up in the hash table built from the smaller - table. - + If the bucket (determined by the hash) contains any entries, check each - entry to see if the join key actually matches the join key of the record - from the probe table (since hash functions can lead to collisions). + + Take each record from the larger table, which is often referred to as the + "probe table." + + Compute the hash on the join key (same hash function used in the build phase). + + Use this hash value to look up in the hash table built from the smaller table. + + If the bucket (determined by the hash) contains any entries, check each entry to + see if the join key actually matches the join key of the record from the probe + table (since hash functions can lead to collisions). + Output the Joined Rows. - = Relational-algebra == Equivalence rules ++ $ sigma_(theta_1 and theta_2)(E) = sigma_theta_1(sigma_theta_2(E)) $ ++ $ sigma_theta_1(sigma_theta_2(E)) = sigma_theta_2(sigma_theta_1(E)) $ ++ $ Pi_L_1(Pi_L_2(...(Pi_L_n (E))...)) = Pi_L_1(E) $ -- only the last one matters. ++ Selections can be combined with Cartesian products and theta joins: + $ sigma_theta (E_1 times E_2) = E_1 join_theta E_2 $ + $ sigma_theta_1 (E_1 join_theta_2 E_2) = E_1 join_theta_1 and theta_2 E_2 $ ++ $ E_1 join_theta E_2 = E_2 join_theta E_1 $ ++ Join associativity: $ (E_1 join E_2) join E_3 = E_1 join (E_2 join E_3) $ + $ (E_1 join_theta_1 E_2) join_(theta_2 and theta_3) E_3 = E_1 join_(theta_1 and theta_3) (E_2 join_theta_2 E_3) $ ++ Selection distribution: + $ sigma_theta_1 (E_1 join_theta E_2) = (sigma_theta_0(E_1)) join_theta E_2 $ + $ sigma_(theta_1 and theta_2)(E_1 join_theta E_2) = (sigma_theta_1 (E)1)) join_theta (sigma_theta_2 (E_2)) $ ++ Projection distribution: + $ Pi_(L_1 union L_2) (E_1 join_theta E_2) = (Pi_L_1 (E_1) join_theta (Pi_L_2 (E_2))) $ + $ Pi_(L_1 union L_2) (E_1 join_theta E_2) = Pi_(L_1 union L_2) ((Pi_(L_1 union L_3) (E_1)) join_theta (Pi_(L_2 union L_4) (E_2))) $ ++ Union and intersection commmutativity: + $ E_1 union E_2 = E_2 union E_1 $ + $ E_1 sect E_2 = E_2 sect E_1 $ ++ Set union and intersection are associative: + $ (E_1 union E_2) union E_3 = E_1 union (E_2 union E_3) $ + $ (E_1 sect E_2) sect E_3 = E_1 sect (E_2 sect E_3) $ ++ The selection operation distributes over the union, intersection, and + set-difference operations: + $ sigma_P (E_1 - E_2) = sigma_P(E_1) - E_2 = sigma_P(E_1) - sigma_P(E_2) $ ++ The projection operation distributes over the union operation: + $ Pi_L (E_1 union E_2) = (Pi_L(E_1)) union (Pi_L(E_2)) $ // FROM Database concepts -+ $σ_(θ_1∧θ_2)(E) ≡σ_(θ_1) (σ_(θ_2)(E))$ -+ $σ_(θ_1)(σ_(θ_2)(E)) ≡σ_(θ_2)(σ_(θ_1)(E))$ -+ $Π_(L_1)(Π_(L_2)(… (Π_(L_n)(E)) …)) ≡Π_(L_1)(E)$ -- only the last one matters. -+ Selections can be combined with Cartesian products and theta joins: $σ_θ(E_1 - × E_2) ≡E_1 ⋈_θ E_2$ - This expression is just the definition of the theta - join |||| $σ_(θ_1)(E_1 ⋈_(θ_2) E_2) ≡E_1 ⋈_(θ_1) ∧ θ_2 E_2$ -+ $E_1 ⋈_θ E_2 ≡E_2 ⋈_θ E_1$ -+ Join associativity: $(E_1 ⋈ E_2) ⋈ E_3 ≡E_1 ⋈(E_2 ⋈E_3)$ |||| $(E_1 join_theta_1 - E_2) join_(theta_2 and theta_3) |||| E_3 ≡E_1 join_(theta_1 or theta_3) (E_2 - join_theta_2 E_3)$ -+ Selection distribution: $σ_(θ_1)(E_1 ⋈_θ E_2) ≡(σ_(θ_1) (E_1)) ⋈_θ E_2$; - $σ_(θ_1∧θ_2)(E_1 ⋈_θ E_2) ≡ (σ_(θ_1)(E_1)) ⋈_θ (σ_(θ_2)(E_2))$ -+ Projection distribution: - $Π_(L_1∪L_2) (E_1 ⋈_θ E_2) ≡(Π_(L_1(E_1)) ⋈_θ - (Π_(L_2)(E_2))$ |||| $Π(L_1∪L_2) (E_1 ⋈_θ E_2) ≡Π_(L_1∪L_2) ((Π_(L_1∪L_3) (E_1)) - ⋈_θ (Π_(L_2∪L_4) (E_2)))$ -+ Union and intersection commmutativity: $E_1 ∪E_2 ≡E_2 ∪E_1 |||| - E_1 ∩E_2 ≡E_2 ∩E_1$ -+ Set union and intersection are associative: $(E_1 ∪E_2) ∪E_3 ≡E_1 ∪(E_2 ∪E_3) |||| (E_1 - ∩E_2) ∩E_3 ≡E_1 ∩(E_2 ∩E_3)$; -+ The selection operation distributes over the union, intersection, and - set-difference operations: $σ_θ(E_1 ∪E_2) ≡σ_θ(E_1) ∪σ_θ(E_2) |||| σ_θ(E_1 ∩E_2) ≡σ_θ(E_1) - ∩σ_θ(E_2) |||| σ_θ(E_1 −E_2) ≡σ_θ(E_1) −σ_θ(E_2) |||| σ_θ(E_1 ∩E_2) ≡σ_θ(E_1) ∩E_2 |||| σ_θ(E_1 −E_2) ≡σ_θ(E_1) - −E_2$; -+ The projection operation distributes over the union operation - $Π_L(E_1 - ∪E_2) ≡(Π_L_(E_1)) ∪(Π_L(E_2))$. // == Operations // @@ -243,17 +237,17 @@ $b_b$ blocks are allocated for the input buffer and each output buffer. // Right Outer Join: $R join.r S$. Purpose: Extends join to include non-matching // tuples from one or both relations, filling with nulls. - -= Concurrency - += Concurrency === Conflict -We say that I and J conflict if they are operations by *different transactions* on the -*same data item*, and at least one of these instructions is a *write* operation. -For example: I = read(Q), J = read(Q) -- Not a conflict; I = read(Q), J = -write(Q) -- Conflict; I = write(Q), J = read(Q) -- Conflict; I = write(Q), J = -write(Q) -- Conflict. +We say that $I$ and $J$ conflict if they are operations by *different +transactions* on the *same data item*, and at least one of these instructions is +a *write* operation. For example: +- $I = #[`read(Q)`]$ , $J = #[`read(Q)`]$ -- Not a conflict; +- $I = #[`read(Q)`]$ , $J = #[`write(Q)`]$ -- Conflict; +- $I = #[`write(Q)`]$, $J = #[`read(Q)`]$ -- Conflict; +- $I = #[`write(Q)`]$, $J = #[`write(Q)`]$ -- Conflict. // + I = read(Q), J = read(Q). The order of I and J *does not matter*, since the same // value of Q is read by $T_i$ and $T _j$, regardless of the order. @@ -280,33 +274,35 @@ equivalent*. We can swap only _adjacent_ operations. The concept of conflict equivalence leads to the concept of conflict serializability. We say that a schedule $S$ is *conflict serializable* if it is -conflict equivalent to a serial schedule. +conflict equivalent to a serial schedule. // TODO: rename to precedence === Precedence graph -Simple and efficient method for determining the conflict -seriazability of a schedule. Consider a schedule $S$. We construct a directed -graph, called a precedence graph, from $S$. The set of vertices -consists of all the transactions participating in the schedule. The set of -edges consists of all edges $T_i arrow T_j$ for which one of three conditions holds: +Simple and efficient method for determining the conflict seriazability of a +schedule. Consider a schedule $S$. We construct a directed graph, called a +precedence graph, from $S$. The set of vertices consists of all the transactions +participating in the schedule. The set of edges consists of all edges $T_i arrow T_j$ for +which one of three conditions holds: + $T_i$ executes `write(Q)` before $T_j$ executes `read(Q)`. + $T_i$ executes `read(Q)` before $T_j$ executes `write(Q)`. + $T_i$ executes `write(Q)` before $T_j$ executes `write(Q)`. If the precedence graph for $S$ has a cycle, then schedule $S$ is not conflict -serializable. If the graph contains no cycles, then the schedule $S$ is -conflict serializable. +serializable. If the graph contains no cycles, then the schedule $S$ is conflict +serializable. == Standard isolation levels - *Serializable* usually ensures serializable execution. -- *Repeatable* read allows only committed data to be read and further requires that, - between two reads of a data item by a transaction, no other transaction is allowed - to update it. However, the transaction may not be serializable -- *Read committed* allows only committed data to be read, but does not require re- peatable reads. -- *Read uncommitted* allows uncommitted data to be read. Lowest isolation level allowed by SQL. +- *Repeatable* read allows only committed data to be read and further requires + that, between two reads of a data item by a transaction, no other transaction is + allowed to update it. However, the transaction may not be serializable +- *Read committed* allows only committed data to be read, but does not require re- + peatable reads. +- *Read uncommitted* allows uncommitted data to be read. Lowest isolation level + allowed by SQL. == Protocols @@ -326,50 +322,51 @@ Every cascadeless schedule is also recoverable. === Lock-based -*Shared Lock* -- If a transaction $T_i$ has obtained a shared-mode lock (denoted by $S$) on -item Q, then Ti can read, but cannot write, $Q$. \ +*Shared Lock* -- If a transaction $T_i$ has obtained a shared-mode lock (denoted +by $S$) on item Q, then Ti can read, but cannot write, $Q$. + *Exclusive Lock* -- If a transaction $T_i$ has obtained an exclusive-mode lock (denoted by $X$) on item Q, then Ti can both read and write $Q$. - ==== 2-phased lock protocol *The Two-Phase Locking (2PL)* Protocol is a concurrency control method used in database systems to ensure serializability of transactions. The protocol -involves two distinct phases: *Locking Phase (Growing Phase):* A transaction -may acquire locks but cannot release any locks. During this phase, the -transaction continues to lock all the resources (data items) it needs to -execute. \ *Unlocking Phase (Shrinking Phase):* The transaction releases locks -and cannot acquire any new ones. Once a transaction starts releasing locks, it -moves into this phase until all locks are released. +involves two distinct phases: *Locking Phase (Growing Phase):* A transaction may +acquire locks but cannot release any locks. During this phase, the transaction +continues to lock all the resources (data items) it needs to execute. -==== Problems of locks +*Unlocking Phase (Shrinking Phase):* The transaction releases locks and cannot +acquire any new ones. Once a transaction starts releasing locks, it moves into +this phase until all locks are released. -*Deadlock* is a condition where two or more tasks are each waiting for the -other to release a resource, or more than two tasks are waiting for resources -in a circular chain. -\ *Starvation* (also known as indefinite blocking) occurs -when a process or thread is perpetually denied necessary resources to process -its work. Unlike deadlock, where everything halts, starvation only affects some -while others progress. +==== Problems of locks + +*Deadlock* is a condition where two or more tasks are each waiting for the other +to release a resource, or more than two tasks are waiting for resources in a +circular chain. + +*Starvation* (also known as indefinite blocking) occurs when a process or thread +is perpetually denied necessary resources to process its work. Unlike deadlock, +where everything halts, starvation only affects some while others progress. === Timestamp-based *Timestamp Assignment:* Each transaction is given a unique timestamp when it starts. This timestamp determines the transaction's temporal order relative to -others. *Read Rule:* A transaction can read an object if the last write -occurred by a transaction with an earlier or the same timestamp. *Write Rule:* -A transaction can write to an object if the last read and the last write -occurred by transactions with earlier or the same timestamps. +others. *Read Rule:* A transaction can read an object if the last write occurred +by a transaction with an earlier or the same timestamp. *Write Rule:* A +transaction can write to an object if the last read and the last write occurred +by transactions with earlier or the same timestamps. === Validation-based -Assumes that conflicts are rare and checks for them only at the end of a transaction. -*Working Phase:* Transactions execute without acquiring locks, recording all -data reads and writes. *Validation Phase:* Before committing, each transaction -must validate that no other transactions have modified the data it accessed. -*Commit Phase:* If the validation is successful, the transaction commits and -applies its changes. If not, it rolls back and may be restarted. +Assumes that conflicts are rare and checks for them only at the end of a +transaction. *Working Phase:* Transactions execute without acquiring locks, +recording all data reads and writes. *Validation Phase:* Before committing, each +transaction must validate that no other transactions have modified the data it +accessed. *Commit Phase:* If the validation is successful, the transaction +commits and applies its changes. If not, it rolls back and may be restarted. // === Version isolation @@ -388,39 +385,42 @@ In the *redo phase*, the system replays updates of all transactions by scanning the log forward from the last checkpoint. The specific steps taken while scanning the log are as follows: -+ The list of transactions to be rolled back, undo-list, is initially set to the list - $L$ in the $<#[checkpoint] L>$ log record. -+ Whenever a normal log record of the form $$, or a redo- - only log record of the form $$ is encountered, the operation is ++ The list of transactions to be rolled back, undo-list, is initially set to the + list + $L$ in the $<#[checkpoint] L>$ log record. ++ Whenever a normal log record of the form $$, or a redo- only + log record of the form $$ is encountered, the operation is redone; that is, the value $V_2$ is written to data item $X_j$. + Whenever a log record of the form $$ is found, $T_i$ is added to undo-list. -+ Whenever a log record of the form $$ or $$ is found, ++ Whenever a log record of the form $$ or $$ is + found, $T_i$ is removed from undo-list. -At the end of the redo phase, undo-list contains the list of all transactions that -are incomplete, that is, they neither committed nor completed rollback before the crash. -\ In the *undo phase*, the system rolls back all transactions in the undo-list. -It performs rollback by scanning the log backward from the end: +At the end of the redo phase, undo-list contains the list of all transactions +that are incomplete, that is, they neither committed nor completed rollback +before the crash. + +In the *undo phase*, the system rolls back all transactions in the undo-list. It +performs rollback by scanning the log backward from the end: + Whenever it finds a log record belonging to a transaction in the undo-list, it performs undo actions just as if the log record had been found during the rollback of a failed transaction. -+ When the system finds a $$ log record for a transaction $T_i$ in undo- - list, it writes a $$ log record to the log and removes $T_i$ from undo- - list. -+ The undo phase terminates once undo-list becomes empty, that is, the system - has found $$ log records for all transactions that were initially - in undo-list. ++ When the system finds a $$ log record for a transaction $T_i$ in + undo- list, it writes a $$ log record to the log and removes $T_i$ from + undo- list. ++ The undo phase terminates once undo-list becomes empty, that is, the system has + found $$ log records for all transactions that were initially in + undo-list. == Log types - $$ -- an update log record, indicating that transaction - $T_i$ has performed a write on data item $X_j$. $X_j$ had value $V_1$ before - the write and has value $V_2$ after the write; + $T_i$ has performed a write on data item $X_j$. $X_j$ had value $V_1$ before the + write and has value $V_2$ after the write; - $$ -- $T_i$ has started; - $$ -- $T_i$ has committed; - $$ -- $T_i$ has aborted; - $<#[checkpoint] {T_0, T_1, dots, T_n}>$ -- a checkpoint with a list of active transactions at the moment of checkpoint. - From 3f4261e918c3423fd2758a97fd3ce6b9c4447bce Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Mon, 6 May 2024 21:56:11 +0300 Subject: [PATCH 5/8] minor changes --- .gitignore | 3 +- main.typ | 99 ++++++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 83 insertions(+), 19 deletions(-) diff --git a/.gitignore b/.gitignore index 955a508..a136337 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1 @@ -cheatsheet.pdf -main.pdf +*.pdf diff --git a/main.typ b/main.typ index a4a8da8..28fd89e 100644 --- a/main.typ +++ b/main.typ @@ -1,6 +1,6 @@ #import "@preview/tablex:0.0.8": tablex, rowspanx, colspanx #set page(margin: 0.6cm, columns: 3) - +#set par(justify: true) #set text(6pt) #show heading: it => { if it.level == 1 { @@ -17,13 +17,13 @@ Each bit in a bitmap corresponds to a possible item or condition, with a bit set to 1 indicating presence or true, and a bit set to 0 indicating absence or -false. +`false`. #tablex( stroke: 0.5pt, columns: 4, [record number], `ID`, `gender`, `income_level`, `0`, `76766`, `m`, `L1`, `1`, `22222`, `f`, `L2`, `2`, `12121`, `f`, `L1`, `3`, `15151`, `m`, `L4`, `4`, `58583`, `f`, `L3`, ) #grid( - columns: 3, gutter: 2em, tablex( + columns: 2, gutter: 2em, tablex( stroke: 0.5pt, columns: 2, colspanx(2)[Bitmaps for `gender`], `m`, `10010`, `f`, `01101`, ), tablex( stroke: 0.5pt, columns: 2, colspanx(2)[Bitmaps for `income_level`], `L1`, `10010`, `L2`, `01000`, `L3`, `00001`, `L4`, `00010`, `L5`, `00000`, @@ -37,8 +37,8 @@ sorted and allows searches, sequential access, insertions, and deletions in logarithmic time. It is an extension of the B-tree and is extensively used in databases and filesystems for indexing. B+ tree is *Balanced*; Order (n): Defined such that each node (except root) can have at most $n$ children -(pointers) and at least $⌈n/2⌉$ children; *Internal nodes hold* between -$⌈n/2⌉−1$ and $n−1$ keys (values); Leaf nodes hold between $⌈frac(n −1, 2)⌉$ and +(pointers) and at least $ceil(n/2)$ children; *Internal nodes hold* between +$ceil(n/2)−1$ and $n−1$ keys (values); Leaf nodes hold between $ceil((n−1)/2)$ and $n−1$ keys, but also store all data values corresponding to the keys; *Leaf Nodes Linked*: Leaf nodes are linked together, making range queries and sequential access very efficient. @@ -47,17 +47,17 @@ sequential access very efficient. - Insert key in the appropriate leaf node in sorted order; - If the node overflows (more than $n−1$ keys), split it, add the middle key to the parent, and adjust pointers; - + Leaf split: $1$ to $ceil(frac(n, 2)) $ and $ceil(frac(n, 2)) + 1 $ to + + Leaf split: $1$ to $ceil(n/2) $ and $ceil(n/2) + 1 $ to $n$ as two leafs. Promote the lowest from the 2nd one. - + Node split: $1$ to $ceil(frac(n+1, 2)) - 1 $ and $ceil(frac(n, 2)) + 1$ to $n$. - $ceil(frac(n+1, 2))$ gets moved up. + + Node split: $1$ to $ceil((n+1)/2) - 1 $ and $ceil(n/2) + 1$ to $n$. + $ceil(n+1/2)$ gets moved up. - If a split propagates to the root and causes the root to overflow, split the root and create a new root. Note: root can contain less than - $ceil(frac(n, 2)) - 1$ keys. + $ceil(n/2) - 1$ keys. - *Delete (key)*: - Remove the key from the leaf node. - - If the node underflows (fewer than $⌈n/2⌉−1$ keys), keys and pointers are - redistributed or nodes are merged to maintain minimum occupancy. - + - If the node underflows (fewer than $ceil(n/2)−1$ keys), keys and pointers are + redistributed or nodes are merged to maintain minimum occupancy. Adjustments may propagate up to ensure all properties are maintained. == Hash-index @@ -82,7 +82,7 @@ tuple of the outer table is compared against every tuple of the inner table to find all pairs of tuples which satisfy the join condition. This method is simple but can be inefficient for large datasets due to its high computational cost. -``` +```python Simplified version (to get the idea) for each tuple tr in r: (for each tuple ts in s: test pair (tr, ts)) ``` @@ -100,7 +100,7 @@ in memory and then loops through the inner table, reducing the number of disk accesses and improving performance over a standard nested loop join, especially when indices are not available. -``` +```python Simplified version (to get the idea) for each block Br of r: for each block Bs of s: for each tuple tr in r: (for each tuple ts in s: test pair (tr, ts)) @@ -199,9 +199,9 @@ $b_b$ blocks are allocated for the input buffer and each output buffer. $ (E_1 sect E_2) sect E_3 = E_1 sect (E_2 sect E_3) $ + The selection operation distributes over the union, intersection, and set-difference operations: - $ sigma_P (E_1 - E_2) = sigma_P(E_1) - E_2 = sigma_P(E_1) - sigma_P(E_2) $ + $ sigma_P (E_1 - E_2) = sigma_P (E_1) - E_2 = sigma_P (E_1) - sigma_P (E_2) $ + The projection operation distributes over the union operation: - $ Pi_L (E_1 union E_2) = (Pi_L(E_1)) union (Pi_L(E_2)) $ + $ Pi_L (E_1 union E_2) = (Pi_L (E_1)) union (Pi_L (E_2)) $ // FROM Database concepts @@ -269,7 +269,7 @@ a *write* operation. For example: == Conflict-serializability If a schedule $S$ can be transformed into a schedule $S'$ by a series of swaps -of non- conflicting instructions, we say that $S$ and $S'$ are *conflict +of non-conflicting instructions, we say that $S$ and $S'$ are *conflict equivalent*. We can swap only _adjacent_ operations. The concept of conflict equivalence leads to the concept of conflict @@ -282,7 +282,7 @@ conflict equivalent to a serial schedule. Simple and efficient method for determining the conflict seriazability of a schedule. Consider a schedule $S$. We construct a directed graph, called a precedence graph, from $S$. The set of vertices consists of all the transactions -participating in the schedule. The set of edges consists of all edges $T_i arrow T_j$ for +participating in the schedule. The set of edges consists of all edges $T_i -> T_j$ for which one of three conditions holds: + $T_i$ executes `write(Q)` before $T_j$ executes `read(Q)`. @@ -424,3 +424,68 @@ performs rollback by scanning the log backward from the end: - $$ -- $T_i$ has aborted; - $<#[checkpoint] {T_0, T_1, dots, T_n}>$ -- a checkpoint with a list of active transactions at the moment of checkpoint. + +== Task +Pieņemsim, ka ir divas relācijas $r_1$ un $r_2$ ar atbilstošiem atribūtiem $r_1(A,B)$ un $r_2(B,C,D,E)$. +Relācijā $r_1$ ir $51105$ raksti, relācijā $r_2$ ir $320251$ raksti. Pieņemsim, +ka vienā blokā ietilpst $27$ relācijas $r_1$ raksti un $25$ relācijas $r_2$ raksti. +Relācijas tiek joinotas $(r_1 join r_2)$ izmantojot _block nested-loop join_ algoritmu. +Cik bloki ir minimālais atmiņas *apjoms $M$ (skaitlis!)*, lai būtu nepieciešams +ne vairāk kā ++ $130000$ bloku pārraides (transfers) no diska ++ $25000$ bloku pārraides (transfers) no diska + +$ T=ceil(b_r/(M-2)) dot b_s+b_r ==> M approx ceil((b_s b_r)/(T-b_r))+2 $ + +$ + b_(r_1)=ceil(51105/27)=1893; + b_(r_2)=ceil(320251/25)=12811 +$ + +== Task +Pieņemsim, ka ir divas relācijas $r_1$ un $r_2$ ar atbilstošiem atribūtiem $r_1(A,B)$ un $r_2(B,C,D,E)$. +Relācijā $r_1$ ir $75435$ raksti, relācijai $r_2$ ir $11456$ raksti. Pieņemsim, +ka vienā blokā ietilpst $22$ relācijas $r_1$ raksti un $35$ relācijas $r_2$ raksti. +Pieņemsim, ka ir pieejami $5$ atmiņas bloki konkrētā algoritma izpildei. Viena +bloka pārraidei no diska nepieciešamas $0.001 "ms"$, bloka meklēšanai -- $0.1 "ms"$. +Uzrakstīt aprēķina formulas un savus pieņēmumus, kā arī aprēķināt skaitliski, +cik minimāli laika (ms) nepieciešams, lai izrēķinātu $r_1 join r_2$, izmantojot +_block join_ un _nested-loop join_. Neņemiet vērā laiku, ko prasa gala rezultāta +ierakstīšana diskā un neņemt vērā procesora laiku, kas patērēts šai operācijai. +Ņemt vērā tikai bloku meklēšanas un lasīšanas laikus. + +=== +$|r_1|=75435; |r_2|=11456$\ +$b_r_1=22; b_r_2=35$\ +$B=5;T_"disk"=0.001;T_"seek"=0.1$ + +=== Block Join method ++ *Memory Limitation*: Only 5 blocks available. ++ Blocks Needed for $r_1$ and $r_2$: + - $r_1: ceil(75435/22)=3429$ + - $r_2: ceil(11456/35)=328$ ++ *Strategy:* + - Use 1 block for $r_1$ and 4 blocks for $r_2$ (or vice versa depending on which + is more efficient). + - This setup means you can have 4 blocks of $r_2$ loaded into memory, storing up + to $4 dot 35=140$ patterns of $r_2$ at a time. ++ *Iterations Needed*: + - *For $r_2$:* $ceil(11456/140)=82$ full iterations (each iteration loads $140$ patterns + of $r_2$ into memory). + - *For $r_1$:* Each block of $r_1$ needs to be loaded and processed against all + loaded $r_2$ blocks for each iteration. ++ *Time Calculation for Block Join:* + - Load time for $r_2$ per iteration: $4 dot 0.001 = 0.004 "ms"$ + - Total load time for $r_2$: $82 dot 0.004 = 0.328 "ms"$ + - Join Time per $r_1$ block per $r_2$ iteration: $0.1 "ms"$ (for each block of $r_1$ joined + with 4 blocks of $r_2$) + - Total join time for all $r_1$ blocks per $r_2$ iteration: $3429 dot 0.1= 342.9"ms"$ + - Total join time for all iterations: $343 dot 82 = 28117.8 "ms"$ + +=== Nested-Loop Join Method ++ Nested-loop join: + - For each pattern in $r_1$, search all patterns in $r_2$. ++ Total Combinations: $75435 dot 11456=$ ++ Time Calculation for Nested-Loop Join: + - Reading and searching time for each combination: $0.001+0.1=0.101 "ms"$ + - Total time: $75435 dot 11456 dot 0.101 = 87282519.36 "ms"$ From 1bf92654da2a04069ff46539ff6f267b1640ae21 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Mon, 6 May 2024 22:03:08 +0300 Subject: [PATCH 6/8] chore: add actions add main file --- .github/workflows/typst.yml | 29 +++++++++++++++++++++++++++++ img/bitmap.png | Bin 43033 -> 0 bytes 2 files changed, 29 insertions(+) create mode 100644 .github/workflows/typst.yml delete mode 100644 img/bitmap.png diff --git a/.github/workflows/typst.yml b/.github/workflows/typst.yml new file mode 100644 index 0000000..415f375 --- /dev/null +++ b/.github/workflows/typst.yml @@ -0,0 +1,29 @@ +name: Build Typst document +on: [push, workflow_dispatch] +permissions: + contents: write +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Typst + uses: lvignoli/typst-action@main + with: + source_file: | + main.typ + - name: Upload PDF file + uses: actions/upload-artifact@v3 + with: + name: PDF + path: "*.pdf" + - name: Get current date + id: date + run: echo "DATE=$(date +%Y-%m-%d-%H:%M)" >> $GITHUB_ENV + - name: Release + uses: softprops/action-gh-release@v1 + if: github.ref_type == 'tag' + with: + name: "${{ github.ref_name }} — ${{ env.DATE }}" + files: main.pdf diff --git a/img/bitmap.png b/img/bitmap.png deleted file mode 100644 index a2998eaecb65940ebaa7155e7ac814bbe7a503a3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43033 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�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 From f6128287add4f820168c16a6b268cc82db4a3818 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Mon, 6 May 2024 22:08:40 +0300 Subject: [PATCH 7/8] Create LICENSE --- LICENSE | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..905f5b3 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 Kristofers Solo + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. From f3345f7cc19eca447c3864b1f8c1d31aec987570 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Mon, 6 May 2024 22:35:59 +0300 Subject: [PATCH 8/8] fix: skill issue --- main.typ | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.typ b/main.typ index 28fd89e..8f24c65 100644 --- a/main.typ +++ b/main.typ @@ -26,7 +26,7 @@ to 1 indicating presence or true, and a bit set to 0 indicating absence or columns: 2, gutter: 2em, tablex( stroke: 0.5pt, columns: 2, colspanx(2)[Bitmaps for `gender`], `m`, `10010`, `f`, `01101`, ), tablex( - stroke: 0.5pt, columns: 2, colspanx(2)[Bitmaps for `income_level`], `L1`, `10010`, `L2`, `01000`, `L3`, `00001`, `L4`, `00010`, `L5`, `00000`, + stroke: 0.5pt, columns: 2, colspanx(2)[Bitmaps for `income_level`], `L1`, `10100`, `L2`, `01000`, `L3`, `00001`, `L4`, `00010`, `L5`, `00000`, ), )