]> git.llucax.com Git - z.facultad/75.06/emufs.git/blob - doc/informe_2da_entrega.lyx
aac4c331413a128670ea5bd7f820481ef2d131d1
[z.facultad/75.06/emufs.git] / doc / informe_2da_entrega.lyx
1 #LyX 1.3 created this file. For more info see http://www.lyx.org/
2 \lyxformat 221
3 \textclass book
4 \language spanish
5 \inputencoding auto
6 \fontscheme palatino
7 \graphics default
8 \paperfontsize default
9 \spacing single 
10 \papersize a4paper
11 \paperpackage widemarginsa4
12 \use_geometry 0
13 \use_amsmath 0
14 \use_natbib 0
15 \use_numerical_citations 0
16 \paperorientation portrait
17 \secnumdepth 3
18 \tocdepth 3
19 \paragraph_separation indent
20 \defskip medskip
21 \quotes_language english
22 \quotes_times 2
23 \papercolumns 1
24 \papersides 1
25 \paperpagestyle default
26
27 \layout Title
28
29 Organización de Datos (75.06)
30 \newline 
31 Trabajo Práctico
32 \newline 
33 E
34 \begin_inset Formula $\mu$
35 \end_inset 
36
37 FS
38 \layout Author
39
40
41 \series bold 
42 Grupo 11
43 \series default 
44
45 \newline 
46 Nicolás Dimov (77624)
47 \newline 
48 Alan Kennedy (78907)
49 \newline 
50 Leandro Lucarella (77891)
51 \newline 
52 Ricardo Markiewicz (78226)
53 \layout Date
54
55 Segunda Entrega, 31 de Mayo de 2004
56 \layout Standard
57
58
59 \begin_inset LatexCommand \tableofcontents{}
60
61 \end_inset 
62
63
64 \layout Chapter
65
66 Introducción
67 \layout Standard
68
69 En esta entrega el trabajo estuvo concentrado en el manejo de índices para
70  los tipos de archivos implementados en la primer entrega.
71  Los índices se implementaron con:
72 \layout Enumerate
73
74 Árbol B
75 \layout Enumerate
76
77 Árbol B*
78 \layout Enumerate
79
80 Árbol B+
81 \layout Standard
82
83 Además de esto, se pide 3 funciones distintas para estos índices:
84 \layout Enumerate
85
86 Principal
87 \layout Enumerate
88
89 Selectivo
90 \layout Enumerate
91
92 Exhaustivo
93 \layout Standard
94
95 Con la autorización de los ayudantes de la cátedra decidimos que el árbol
96  B+ sólo pueda ser utilizado para índices principal ya que de otra manera
97  no tiene sentido el set secuencial (ver página 
98 \begin_inset LatexCommand \pageref{sub:justificacion}
99
100 \end_inset 
101
102  para una justificación más detallada).
103 \layout Standard
104
105 Finalmente, para obtener listados basados en campos de los cuales no se
106  tiene un índice, se implementó un ordenamiento externo.
107 \layout Standard
108
109 A continuación se presenta una descripción un poco más detallada sobre todas
110  herramientas utilizadas para resolver el trabajo práctico.
111 \layout Section
112
113 Documentación de la API
114 \layout Standard
115
116 Para obtener una documentación de la API más completa, se incluye en formato
117  HTML en el CD-ROM la documentación generado con Doxygen.
118  Esta documentación se encuentra en el directorio 
119 \family typewriter 
120 doc/api/html/index.html
121 \family default 
122 .
123 \layout Chapter
124
125 Estructura común
126 \layout Section
127
128 Tipos
129 \layout Standard
130
131 Se detallan a continuación los tipos de datos definidos y utilizados en
132  las distintas implementaciones que conforman nuestro sistema, siendo el
133  más importante de ellos en esta entrega, la estructura 
134 \family typewriter 
135 INDICE
136 \family default 
137  que actúa como interfaz común para el manejo de cualquier tipo de índice
138  (no importa que tipo de organización física ni de que forma esté implementado,
139  esta estructura proveerá una interfaz abstracta para su manejo).
140 \layout Subsection
141
142 Tipos Comunes
143 \layout Standard
144
145 Se agregaron varios tipos comunes nuevos en esta entrega, en su mayoría
146  relacionados a los índices.
147  Estos tipos son brevemente descriptos a continuación y pueden ser hallados
148  en el archivo 
149 \family typewriter 
150 indices.h
151 \family default 
152 :
153 \layout Itemize
154
155
156 \family typewriter 
157 INDICE_DATO
158 \family default 
159 : usado para representar el conjunto de un ID más su dato.
160 \layout Itemize
161
162
163 \family typewriter 
164 INDICE_TIPO
165 \family default 
166 : indica el tipo de índice (B, B* o B+).
167 \layout Itemize
168
169
170 \family typewriter 
171 INDICE_FUNCION
172 \family default 
173 : indica la función que cumple el índice (principal, selectivo o exhaustivo).
174 \layout Itemize
175
176
177 \family typewriter 
178 INDICE_TIPO_DATO
179 \family default 
180 : indica el tipo de dato que se usa como clave.
181 \layout Itemize
182
183
184 \family typewriter 
185 CLAVE
186 \family default 
187 : representa una clave de un índice.
188 \layout Subsection
189
190 INDICE
191 \layout Standard
192
193
194 \family typewriter 
195 INDICE
196 \family default 
197 \emph on 
198  
199 \emph default 
200 es la estructura principal que encapsula todas las funciones para el manejo
201  de un índice.
202  Posee punteros a funciones que permite utilizar la misma interfaz para
203  distintas implementaciones de árboles.
204  
205 \layout Standard
206
207 Su declaración puede ser observada en el archivo 
208 \family typewriter 
209 indices.h
210 \family default 
211 \series bold 
212  
213 \series default 
214 y cuenta con la siguiente información:
215 \layout Itemize
216
217 Tipo de índice.
218 \layout Itemize
219
220 Tipo de dato que maneja.
221 \layout Itemize
222
223 Función del índice.
224 \layout Itemize
225
226 Información sobre el desplazamiento para ubicar el dato dentro de la estructura
227  a indexar (para poder tener una implementación genérica que sirva para
228  cualquier estructura).
229 \layout Itemize
230
231 Información sobre archivos auxiliares para almacenar cadenas de texto y
232  otras estructuras que eventualmente requiera un índice.
233 \layout Itemize
234
235 Punteros a funciones para:
236 \begin_deeper 
237 \layout Itemize
238
239 Agregar entrada.
240 \layout Itemize
241
242 Borrar entrada.
243 \layout Itemize
244
245 Verificar la existencia de una entrada.
246 \layout Itemize
247
248 Buscar entradas.
249 \layout Itemize
250
251 Obtener clave menor o mayor del índice.
252 \layout Itemize
253
254 Obtener siguiente clave (para recorrido secuencial).
255 \end_deeper 
256 \layout Standard
257
258 Esta estructura define los valores de sus punteros según el tipo de implementaci
259 ón que se desee manejar y esto se realiza a través de la API 
260 \family typewriter 
261 emufs_indice
262 \family default 
263 , implementada en 
264 \family typewriter 
265 indices.h
266 \family default 
267 .
268  Esta API posee funciones para crear y destruir índices, agregarlos y quitarlos
269  de una estructura 
270 \family typewriter 
271 EMUFS
272 \family default 
273 , comparar claves y otras, necesarias para la correcta y completa utilización
274  de los índices a través de la interfaz de 
275 \family typewriter 
276 EMUFS
277 \family default 
278  descripta en la entrega anterior.
279 \layout Subsubsection
280
281 Integración con 
282 \family typewriter 
283 EMUFS
284 \family default 
285 .
286 \layout Standard
287
288 Para integrar la utilización de índices a 
289 \family typewriter 
290 EMUFS
291 \family default 
292  fueron necesarios los siguientes cambios:
293 \layout Paragraph
294
295 Nuevos tipos de archivo.
296 \layout Standard
297
298 Se incluyen dos tipos de archivo nuevos T4 y T5, que representan, respectivament
299 e, un archivo T1 (registros variables, bloques fijos) y un archivo T3 (registros
300  y bloques fijos), ambos organizados como un set secuencial indexado.
301  De esta manera se conserva la interfaz de 
302 \family typewriter 
303 EMUFS
304 \family default 
305  (los punteros a funciones) incluso cuando se debe insertar de forma ordenada,
306  ya que al saber que es T4 o T5 siempre se inserta de forma ordenada.
307 \layout Paragraph
308
309 Puntero a un arreglo de índices.
310 \layout Standard
311
312 Se agrega a la estructura 
313 \family typewriter 
314 EMUFS
315 \family default 
316  un puntero a un arreglo de 
317 \family typewriter 
318 INDICE
319 \family default 
320 , donde el primero es siempre el índice principal.
321 \layout Chapter
322
323 Especificaciones de índices
324 \layout Section
325
326 Indice B
327 \layout Standard
328
329 En esta sección no se explicará como funciona la implementación del árbol
330  B, sino que se darán algunos detalles de la implementación para algunos
331  casos particulares.
332 \layout Standard
333
334 Cada nodo del árbol cuenta con un header y un array de datos, donde cada
335  dato contiene, entre otras cosas la clave, el dato al que apunta (id/bloque
336  del archivo de datos) y el hijo derecho (aquel nodo que contiene las claves
337  superiores).
338  En el header se guarda el puntero (número de nodo) al hijo izquierdo, que
339  viene a ser el nodo que contiene claves menores a la primer clave de nodo
340  actual.
341 \layout Standard
342
343 Existen 2 casos particulares para lo que contiene la clave y el dato.
344  El primer caso se da cuando la clave es de tipo string.
345 \layout Standard
346
347 Cuando un índice debe almacenar string, estos no son guardados en el árbol,
348  sino que se reutiliza la estructura EMUFS de la primer entrega para guardar
349  las cadenas de texto, utilizano para ello una organización de registros
350  de longitud variable sin bloques, elegida de forma arbitraria.
351  En la clave del arbol se guardará entonces el ID del registro que contiene
352  el texto en la estructura mencionada anteriormente.
353  Cuando se quiere recuperar una clave, se lee el archivo que contiene las
354  claves de texto (que permanecen abreviadas).
355 \layout Standard
356
357 El otro caso particular es para los índices con clave repetida (como ser
358  el selectivo y el exahustivo).
359  Para este caso lo que cambia es lo que se almacena en el campo DATO que
360  acompaña a la clave.
361  Este DATO contendra el ID de un registro que se guarda nuevamente en un
362  EMUFS en formato de registro de longitud variable sin bloques, donde estarán
363  los ID/Bloque reales del archivo de dato de todas las ocurrencias de la
364  clave correspondiente.
365 \layout Standard
366
367 Cada vez que se inserta una clave y ya existia una previa, se agrega a dicho
368  arreglo la nueva posicion y luego se guarda.
369  Si al eliminar todos los datos de una clave este array quedara vacio, la
370  clave es eliminada del árbol.
371 \layout Standard
372
373 Puede darse el caso (es más, casi todos los índices utilizados en el TP
374  son de esta manera) que ocurran ambas situaciones descriptas anteriormente,
375  por lo que para un índice, por ejemplo de presentación de los artículos,
376  se tenga que acceder a 9 archivos (el arbol B, 4 para los string, 4 para
377  las claves repetidas) para obtener todos los ID del archivo de datos para
378  mostrar en pantalla.
379  Con esta falla de diseño y todo el acceso a registros por campos de identificac
380 ión no único es muy superior a realizar una búsqueda secuencial sobre todo
381  el archivo para realizar una consultas.
382 \layout Section
383
384 Indice B*
385 \layout Standard
386
387 Lo único que se reescribió fue la función insertar, que aunque es muy similar
388  al del otro árbol, meter más codigo en la misma función hacía aún más dificil
389  de mantener y debuggear el árbol.
390 \layout Standard
391
392 Otro cambio a la API de árbol B fue en el borrar, que mediante una macro
393  se verifica que tipo de árbol se está tratando y en base a eso se calcula
394  la cantidad de hijos mínimos antes de fundir 2 nodos (o pedir una clave
395  a algún hermano).
396 \layout Subsection
397
398 Decisiones de diseño
399 \layout Standard
400
401 Una de las pocas decisiones que tuvimos que tomar fue la forma de manejar
402  el nodo raíz.
403  Hay dos formas comunes de hacerlo:
404 \layout Enumerate
405
406 Permitir que el nodo raíz pueda almacenar 2N+1 claves (siendo N el número
407  máximo de claves permitido por nodo).
408 \layout Enumerate
409
410 Hacer que se comporte como un árbol B.
411 \layout Standard
412
413 La primera forma garantiza un mejor aprovechamiento del espacio, ya que
414  se sigue haciendo una partición en 3 nodos hijo con 2/3 de los espacios
415  llenos.
416  El problema que encontramos para hacerlo de esa forma fue que usamos un
417  tamaño de nodo fijo de 512 para poder leer un sector completo del disco
418  y ganar algo de velocidad, por lo que para poder mantener este esquema
419  hubiéramos necesitado de 3 bloques de 512 para poder guardar los 2N+1 claves,
420  desperdiciando 512-tamaño_de_clave espacio en el bloque final y haciendo
421  que cualquier ahorro de espacio en los hijos del nodo raíz difícilmente
422  lo compense.
423 \layout Standard
424
425 Además de esto, el utilizar la segunda forma trae como ventaja la reutilización
426  de código del árbol B, lo que facilita la implementación y el mantenimiento
427  del código.
428 \layout Standard
429
430 Estas son las dos razones principales por las cuales elegimos tratar el
431  nodo raíz como lo hace el árbol B.
432 \layout Section
433
434 Indice B+ Organizacion Secuencial Indexada
435 \layout Subsection
436
437 Decisiones de diseño
438 \layout Standard
439
440 Para la implementación de la organización secuencial indexada de archivos,
441  se ha utilizado un árbol B+, conocido por ser utilizado en términos generales
442  para implementaciones de esta índole.
443 \layout Standard
444
445 Como particularidad el arbol B+, poseerá en sus hojas todas las claves que
446  se hayan insertado en el árbol.
447  No obstante, las mismas no serán todas las claves que se encuentren en
448  el archivo de datos, sino la primer clave de cada bloque de datos, también
449  denominadas 'anclas de bloque'.
450 \layout Standard
451
452 En torno a esta distinción respecto de los demás arboles, el árbol B+ nos
453  indicará a la hora de grabar registros en nuestro archivo de datos con
454  bloques (Organización del TP1, Tipo1 o 3), en que bloque de datos debemos
455  realizar la mencionada inserción.
456  La operativa se detalla más adelante, pero básicamente realizaremos una
457  búsqueda del ancla menor inmediata a la clave del registro que se desea
458  insertar, y esto nos indicará el bloque apropiado (el bloque donde esta
459  el ancla).
460 \layout Standard
461
462 Como resultado concreto de este comportamiento (teniendo en cuenta también
463  el borrado y partición de bloques del .dat), obtendremos un archivo secuencial
464  indexado, en donde los registros se encuentran ordenados a nivel de bloques,
465  esto es, dentro de un bloque dado del archivo de datos, los registros estan
466  ordenados por clave primaria.
467  No obstante, los bloques no estarán necesariamente ordenados, pero igualmente
468  la cantidad de accesos para recorrer el archivo en forma secuencial, se
469  ve minimizada respecto de otras organizaciones, gracias al encadenamiento
470  de las hojas y la posesión de las anclas de bloque, cuya lista resultante
471  del encadenamiento es denominada 
472 \series bold 
473 Sequence Set.
474 \layout Subsubsection
475
476
477 \begin_inset LatexCommand \label{sub:justificacion}
478
479 \end_inset 
480
481 Razones por las cuales el B+ es útil sólo para clave principal.
482 \layout Standard
483
484 El mejor aprovechamiento del Arbol B+ se da en su utilizacion en implementacion
485  ISAM (Indexed Sequential Access Method), en donde se realiza una indexacion
486  parcial de claves, sólo ingresando en el árbol las claves anclas de cada
487  bloque en el archivo de datos.
488  
489 \layout Standard
490
491 Esta aplicación del árbol B+ a ISAM, además de indicarnos donde grabar y
492  donde buscar los registros por identificación primaria, nos asegura el
493  ordenamiento de los registros parcialmente a nivel de bloque (esto es,
494  los registros en un bloque dado, estarán ordenados, pero los bloques no
495  necesariamente).
496  Así pués, recorriendo el Sequence Set del Arbol B+, minimizaremos los saltos
497  de lectura en disco, pues dentro de un bloque indicado por un ancla dada
498  en el Sequence Set, podremos recorrer los registros secuencialmente.
499 \layout Standard
500
501 Visto y considerando que la aplicación más importante a nuestro criterio
502  del Arbol B+, era para la indexacion parcial de claves primarias, y que
503  en caso de utilizarlo para otros índices, el B+ se convertiría simplemente
504  en un B con encadenamiento a nivel de hojas, luego de consultar con los
505  ayudantes, decidimos utilizarlo unicamente para el índice primario, y utilizar
506  el B y B* para los restantes índices y/o el primario.
507  
508 \layout Subsection
509
510 Estructura
511 \layout Standard
512
513 Para comprender mejor la implementación particular que hemos dado al árbol
514  B+, damos una breve reseña de la estructura de un nodo del arbol, la cual
515  es la siguiente:
516 \layout Itemize
517
518 Nivel
519 \layout Itemize
520
521 Cantidad de claves
522 \layout Itemize
523
524 Arreglo de claves
525 \layout Itemize
526
527 Arreglo de hijos
528 \layout Standard
529
530 Esta estructura se encuentra en el archivo 
531 \family typewriter 
532 indice_bplus.h
533 \layout Standard
534
535 Esta organización permite, con la ayuda del árbol, mantener el archivo de
536  datos ordenado por la clave principal.
537 \layout Standard
538
539 Para lograr esto, como fue expuesto anteriormente, el árbol nos indicará
540  donde (en qué bloque) debe insertarse un registro.
541  (ver 3.3.1 Inserción)
542 \layout Standard
543
544 En el caso de una hoja, dado que cada nodo posee un hijo mas que la cantidad
545  de claves, el hijo que sobra será utilizado como referencia al nodo 
546 \begin_inset Quotes eld
547 \end_inset 
548
549 hermano
550 \begin_inset Quotes erd
551 \end_inset 
552
553 , lo cual constituye el 
554 \begin_inset Quotes eld
555 \end_inset 
556
557 set secuencial
558 \begin_inset Quotes erd
559 \end_inset 
560
561  del índice.
562  Para un nodo que no sea hoja el hijo será el número de nodo correspondiente
563  según la clave, es decir, para la clave 
564 \series bold 
565 \emph on 
566
567 \series default 
568 \emph default 
569 el hijo 
570 \series bold 
571 \emph on 
572 n
573 \series default 
574 \emph default 
575  contiene claves menores y el hijo 
576 \series bold 
577 \emph on 
578 n+1
579 \series default 
580 \emph default 
581  contiene las claves mayores.
582  En el caso particular del nivel 1 (index set) el hijo 
583 \series bold 
584 \emph on 
585 n+1
586 \series default 
587 \emph default 
588  (sequence set) contiene las claves mayores o iguales ya que el 
589 \begin_inset Quotes eld
590 \end_inset 
591
592 secuence set
593 \begin_inset Quotes erd
594 \end_inset 
595
596  debe contener todas las claves insertadas, esto produce que exista una
597  repetición de las claves entre el nivel 1 y el 0.
598 \layout Standard
599
600 En nuestro caso hemos implementado un Secuencial Indexado tipo ISAM (Indexed
601  Sequential Access Method) el cual posee en sus hojas las anclas de cada
602  bloque en el archivo de datos, es decir, solo se guardan en los nodos del
603  árbol la menor de las claves de un bloque del archivo de datos, acompañada
604  cada clave por el numero de bloque al cual pertenece.
605 \layout Standard
606
607 Hemos adoptado que la cantidad de claves máxima en un nodo del árbol sea
608  una cantidad impar, ya que esto facilita la elección de la clave que será
609  promovida hacia su nodo padre en caso de que se produzca un overflow en
610  el nodo.
611 \layout Subsection
612
613 Inserción
614 \layout Standard
615
616 Para realizar una inserción en el archivo de datos se debe realizar una
617  consulta en el árbol, la cual nos indicará el número de bloque donde debemos
618  insertar el nuevo registro.
619 \layout Standard
620
621 Las consultas se realizan a través de una estructura INDEX_DAT que posee:
622 \layout Itemize
623
624 Clave
625 \layout Itemize
626
627 Número de Bloque 
628 \layout Standard
629
630 Esta estructura se encuentra en el archivo 
631 \family typewriter 
632 indice_bplus.h
633 \layout Standard
634
635 El modo de uso es el siguiente:
636 \layout Standard
637
638 En primer lugar se carga la clave a insertar en el campo Clave, y en el
639  campo Número de Bloque se almacena un número de bloque válido, mas adelante
640  se explica el por qué.
641 \layout Standard
642
643 Luego se invoca a la función 
644 \family typewriter 
645 int emufs_b_plus_get_bloque(INDICE, INDEX_DAT) 
646 \family default 
647 la cual recibe como parámetro una estructura de índice y un INDEX_DAT para
648  realizar la consulta.
649 \layout Standard
650
651 Esta función recorre recursivamente el árbol y busca una clave mayor inmediata
652  a la enviada, siempre culminando la búsqueda en una hoja.
653  Al encontrar la clave mayor inmediata, el resultado de la búsqueda será
654  la clave anterior en el nodo, pues cada clave en el nodo es un ancla de
655  bloque de datos, de esta manera la clave anterior será menor a la clave
656  enviada, pues las claves en las hojas están ordenadas.
657  
658 \layout Standard
659
660 En este paso pueden suceder dos cosas:
661 \layout Enumerate
662
663 Que exista una clave menor a la enviada.
664 \layout Enumerate
665
666 Que la clave enviada sea menor a todas las claves del árbol.
667 \layout Standard
668
669 En el primer caso, se ha encontrado la clave y se carga la estructura con
670  el hijo de esa clave, que será el número de bloque donde debe insertarse
671  el nuevo registro (por el cual se realizó la consulta), sobreescribiendo
672  el valor que almacenaba al ingresar, y la función retornará código 0 que
673  indica que se ha encontrado un bloque donde insertar.
674 \layout Standard
675
676 En el segundo caso, puede darse que la clave enviada sea menor a todas las
677  claves del árbol, por lo cual no es posible encontrar un ancla de bloque
678  para esa clave.
679  Aquí la función retornará código -1 lo cual indica que no se ha encontrado
680  un bloque donde insertar el registro nuevo, y es por esto que la estructura
681  debe inicializarse con un número de bloque válido antes de realizarse la
682  consulta.De esta manera el árbol indica donde debe insertarse un nuevo registro
683  en el archivo de datos.
684 \layout Standard
685
686 Otro detalle de la inserción es que cuando el árbol indica donde debe insertarse
687  un registro pueden pasar dos cosas nuevamente:
688 \layout Enumerate
689
690 Que el registro quepa en el bloque.
691 \layout Enumerate
692
693 Que el registro no quepa en el bloque.
694 \layout Standard
695
696 El primer caso es trivial y el registro se insertará sin problemas en el
697  bloque indicado.
698 \layout Standard
699
700 En el caso que el registro no quepa en el bloque, se deberán separar los
701  registros del bloque en 2 bloques, en original y uno nuevo, cada uno con
702  la mitad (aproximadamente) de los registros.
703  
704 \layout Standard
705
706 Al partir el bloque el ancla del bloque original no se modificará, pero
707  en el bloque nuevo se crea una nueva anlca de bloque, pues una de las claves
708  pertenecientes a los registros que contiene, será la menor.
709 \layout Standard
710
711 Antes de actualizar el árbol con el ancla nueva, habrá que discriminar en
712  qué bloque se debe insertar el registro nuevo.
713  Para ello se compara la menor de las claves del nuevo bloque con la clave
714  del registro, si la clave del registro es menor que el ancla del nuevo
715  bloque, este debe ir en el bloque original, y se inserta ordenado en él
716  y se le informa al árbol que actualice (inserte) una nueva clave correspondient
717 e al bloque nuevo, sino se inserta en el bloque nuevo de forma ordenada
718  y en este caso cabe la posibilidad de que el nuevo registro posea la clave
719  mas pequeña de todas en el bloque, por ello se lo inserta ordenadamente
720  con ayuda de la función
721 \family typewriter 
722  CLAVE grabar_ordenado_en_bloque(EMUFS *emu, void *ptr, EMUFS_REG_SIZE size,
723  void *bloque, int num_bloque, EMUFS_FREE fs, int *err) 
724 \family default 
725 la cual inserta el registro ordenado por CLAVE y devuelve la menor de las
726  claves del bloque, que se usará para informarle al árbol que inserte una
727  clave nueva junto con el número de bloque, para indexar este bloque.
728 \layout Subsection
729
730 Eliminación
731 \layout Standard
732
733 El proceso de eliminación es bastante similar al de inserción en el sentido
734  que también hay que realizar una consulta en el árbol para obtener el número
735  de bloque al que pertenece una clave.
736  Una vez conocido este número se levanta el bloque correspondiente y se
737  busca secuencialmente el registro que se debe eliminar.
738 \layout Standard
739
740 Si el registro a eliminar fuera el primero del bloque, habrá que modificar
741  el ancla de bloque en el árbol con el ancla que corresponda a la clave
742  del nuevo menor registro, y si el que se elimina fuera el único registro
743  en el bloque habrá que eliminar la clave del árbol.
744 \layout Standard
745
746 En cualquier otro caso, solo se eliminará el registro correspondiente y
747  se justificarán los registros a izquierda.
748 \layout Subsection
749
750 Búsqueda
751 \layout Standard
752
753 El proceso de búsqueda de un registro por su clave de identificación primaria
754  en la Organización Secuencial Indexada, es bastante directa en su entendimiento.
755  Para buscar un registro, acudiremos al árbol B+ con la clave anteriormente
756  mencionada, y obtendremos del mismo, el número de bloque donde se debe
757  encontrar el registro.
758 \layout Standard
759
760 Para obtener dicho número de bloque, el árbol internamente busca el ancla
761  menor inmediata a la clave buscada y luego devuelve el número de bloque
762  de datos donde está dicha ancla (el nro bloque será el dato asociado a
763  la clave ancla, en el árbol), el cual será el bloque potencial donde se
764  encuentre el registro buscado.
765 \layout Standard
766
767 Una desventaja de esta implementación con indexación parcial, es que no
768  sabremos si el registro se encuentra efectivamente en el bloque indicado,
769  hasta no buscarlo dentro del mismo en formal secuencial.
770  Si lo hallamos, daremos por finalizada la búsqueda del registro.
771 \layout Subsection
772
773 Recorrida secuencial de registros
774 \layout Standard
775
776 Una consecuencia importante de la organización secuencial indexada, en este
777  caso implementada a través de un árbol B+ con indexación parcial, es que
778  como mencionamos anteriormente, los registros dentro de un bloque se encuetran
779  ordenados, y si bien los bloques en si pueden no estar ordenados en el
780  archivo de datos, algunos lo estarán, y minimizarán en base a estas característ
781 icas, los tiempos de acceso para una recorrida secuencial de registros.
782 \layout Standard
783
784 Suponiendo que nos encontramos con varios registros cargados en esta organizació
785 n de archivo, y con el correspondiente árbol de indexación primaria B+ en
786  el disco, si se nos pidiera por ejemplo, recorrer los registros de articulos
787  desde el ID_Articulo 40, hasta el ID_Articulo 1406, la operativa será la
788  siguiente:
789 \layout Itemize
790
791 Acudimos al árbol y obtenemos el numero de bloque para el ID_Articulo 40,
792  buscando el ancla menor inmediata y obteniendo el nro de bloque de datos
793  donde se encuentra, siendo este el nro de bloque donde debería estar el
794  artículo de clave ID_Articulo 40.
795 \layout Itemize
796
797 Levantamos el bloque de datos y lo recorremos secuencialmente, pues como
798  dijimos anteriormente, sus registros se encuentran ordenados por la clave
799  de identificación primaria, en este caso ID_Articulo.
800 \layout Itemize
801
802 Cuando ya hayamos procesado todo el bloque, debemos obtener la siguiente
803  ancla a través del árbol y repetir el proceso.
804 \layout Itemize
805
806 NOTA: Cabe desatacar, que todas las anclas estan en las hojas del B+, y
807  por ello las recorremos a nivel hojas a traves del Sequence Set, que gracias
808  a su encadenamiento, nos permite obtener en forma muy directa y efectiva,
809  las anclas de bloque ordenadas en secuencia, y por consiguiente, recorrer
810  el archivo en forma secuencial minimizando accesos.
811 \layout Chapter
812
813 Ordenamiento Externo
814 \layout Section
815
816 Descripción del algoritmo
817 \layout Standard
818
819 Luego de buscar varias alternativas sobre algoritmos de ordenamiento externo,
820  se optó por el siguiente (que resultó una mezcla de las alternativas analizadas
821 ):
822 \layout Enumerate
823
824 Tomar uno a uno los registros del archivo a ordenar e 
825 \emph on 
826 inyectarlos
827 \emph default 
828  en un buffer ordenado hasta llenar el buffer.
829 \layout Enumerate
830
831 Quitar el menor de los valores (
832 \emph on 
833 inyectando
834 \emph default 
835  uno nuevo desde el archivo a ordenar) e insertarlo en un archivo temporal.
836 \layout Enumerate
837
838 Quitar del buffer el mínimo valor mayor al último insertado en el archivo
839  temporal (
840 \emph on 
841 inyectando
842 \emph default 
843  nuevamente un registro obtenido del archivo a ordenar) y se lo inserta
844  en el archivo temporal.
845  De esta forma quedan ordenados los registros en el archivo temporal.
846 \layout Enumerate
847
848 Repetir el paso 3 hasta que se vacíe el buffer o hasta que no haya ningún
849  valor mayor al último insertado en el archivo temporal.
850  Cuando esto suceda se crea un nuevo archivo temporal volviendo al paso
851  2.
852 \layout Standard
853
854 En este punto ya tenemos el buffer vacío y todos los valores del archivo
855  a ordenar repartidos en 1 o más archivos temporales ordenados, sólo queda
856  unir los archivos para volver a un sólo archivo completo y ordenado.
857  El procedimiento es simple:
858 \layout Enumerate
859
860 Obtener el mínimo valor de los archivos temporales e insertarlo en el archivo
861  ordenado de salida.
862 \layout Enumerate
863
864 Repetir 1 hasta agotar los registros de todos los archivos temporales.
865 \layout Standard
866
867 Debe quedar claro que los archivos temporales se comportan como una cola.
868  Es decir que al obtener un registro de un archivo temporal se obtiene el
869  primer registro que se haya insertado (el mínimo por la forma en la que
870  fueron insertados).
871 \layout Subsection
872
873 Ejemplo
874 \layout Standard
875
876 A continuación se presenta un ejemplo para una más fácil comprensión del
877  algoritmo.
878 \layout Standard
879
880 Supongamos que queremos ordenar un archivo con registros de números enteros
881  (el archivo se lee de izquierda a derecha): 9 6 34 2 8 3 12 43 23 4 19
882  21 87 1 16 36 42 65
883 \layout Standard
884
885 Supongamos que disponemos de un buffer capaz de almacenar 3 registros.
886 \layout Paragraph
887
888 Se llena el buffer ordenado
889 \layout Standard
890
891 Se lee 9 del archivo original y se lo inserta en el buffer ordenado.
892  Buffer: 9
893 \layout Standard
894
895 Se lee 6 del archivo original y se lo inserta en el buffer ordenado.
896  Buffer: 6 9
897 \layout Standard
898
899 Se lee 34 del archivo original y se lo inserta en el buffer ordenado.
900  Buffer: 6 9 34
901 \layout Paragraph
902
903 Se crea el archivo temporal ordenado 1
904 \layout Standard
905
906 Se lee el mínimo valor del buffer (6), se lo inserta en el archivo temporal
907  y se carga un nuevo valor del archivo original al buffer (2).
908  Buffer: 2 9 34.
909  Archivo1: 6
910 \layout Standard
911
912 Se lee el mínimo valor del buffer mayor al insertado anteriormente (9),
913  se lo inserta en el archivo temporal y se carga un nuevo valor del archivo
914  original al buffer (8).
915  Buffer: 2 8 34.
916  Archivo1: 6 9
917 \layout Standard
918
919 Se lee el mínimo valor del buffer mayor al insertado anteriormente (34),
920  se lo inserta en el archivo temporal y se carga un nuevo valor del archivo
921  original al buffer (3).
922  Buffer: 2 3 8.
923  Archivo1: 6 9 34
924 \layout Standard
925
926 No hay más valores en el buffer mayores al último insertado (34), fin del
927  Archivo1.
928 \layout Paragraph
929
930 Se crea el archivo temporal ordenado 2
931 \layout Standard
932
933 Se lee el mínimo valor del buffer (2), se lo inserta en el archivo temporal
934  y se carga un nuevo valor del archivo original al buffer (12).
935  Buffer: 3 8 12.
936  Archivo2: 2
937 \layout Standard
938
939 Se lee el mínimo valor del buffer mayor al insertado anteriormente (3),
940  se lo inserta en el archivo temporal y se carga un nuevo valor del archivo
941  original al buffer (43).
942  Buffer: 8 12 43.
943  Archivo2: 2 3
944 \layout Standard
945
946 Se lee el mínimo valor del buffer mayor al insertado anteriormente (8),
947  se lo inserta en el archivo temporal y se carga un nuevo valor del archivo
948  original al buffer (23).
949  Buffer: 12 23 43.
950  Archivo2: 2 3 8
951 \layout Standard
952
953 Se lee el mínimo valor del buffer mayor al insertado anteriormente (12),
954  se lo inserta en el archivo temporal y se carga un nuevo valor del archivo
955  original al buffer (4).
956  Buffer: 4 23 43.
957  Archivo2: 2 3 8 12
958 \layout Standard
959
960 Se lee el mínimo valor del buffer mayor al insertado anteriormente (23),
961  se lo inserta en el archivo temporal y se carga un nuevo valor del archivo
962  original al buffer (19).
963  Buffer: 4 19 43.
964  Archivo2: 2 3 8 12 23
965 \layout Standard
966
967 Se lee el mínimo valor del buffer mayor al insertado anteriormente (43),
968  se lo inserta en el archivo temporal y se carga un nuevo valor del archivo
969  original al buffer (21).
970  Buffer: 4 19 21.
971  Archivo2: 2 3 8 12 23 43
972 \layout Standard
973
974 No hay más valores en el buffer mayores al último insertado (43), fin del
975  Archivo2.
976 \layout Paragraph
977
978 Se crea el archivo temporal ordenado 3
979 \layout Standard
980
981 Se repite el proceso anterior.
982  Buffer: 1 16 36.
983  Archivo3: 4 19 21 87
984 \layout Paragraph
985
986 Se crea el archivo temporal ordenado 4
987 \layout Standard
988
989 Se repite el proceso anterior.
990  Buffer: .
991  Archivo4: 1 16 36 42 65
992 \layout Paragraph
993
994 Se mezclan los archivos temporales ordenados obteniendo un archivo completo
995  ordenado
996 \layout Standard
997
998 Se obtiene el menor valor de los archivos temporales ordenados (sólo tenemos
999  que elegir entre el primer valor de cada uno).
1000 \layout Standard
1001
1002 Archivo1: 6 9 34.
1003  Archivo2: 2 3 8 12 23 43.
1004  Archivo3: 4 19 21 87.
1005  Archivo4: 1 16 36 42 65
1006 \layout Standard
1007
1008 Sólo debo comparar y obtener el menor entre 6, 2, 4, y 1.
1009  Obtengo el 1, lo saco del archivo temporal y lo agrego al de salida:
1010 \layout Standard
1011
1012 Archivo1: 6 9 34.
1013  Archivo2: 2 3 8 12 23 43.
1014  Archivo3: 4 19 21 87.
1015  Archivo4: 16 36 42 65 Salida: 1
1016 \layout Standard
1017
1018 Repito hasta que no hayan más valores en los archivos temporales:
1019 \layout Standard
1020
1021 Archivo1: 6 9 34.
1022  Archivo2: 3 8 12 23 43.
1023  Archivo3: 4 19 21 87.
1024  Archivo4: 16 36 42 65.
1025  Salida: 1 2
1026 \layout Standard
1027
1028 Archivo1: 6 9 34.
1029  Archivo2: 8 12 23 43.
1030  Archivo3: 4 19 21 87.
1031  Archivo4: 16 36 42 65.
1032  Salida: 1 2 3
1033 \layout Standard
1034
1035 Archivo1: 6 9 34.
1036  Archivo2: 8 12 23 43.
1037  Archivo3: 19 21 87.
1038  Archivo4: 16 36 42 65.
1039  Salida: 1 2 3 4
1040 \layout Standard
1041
1042 Archivo1: 6 9 34.
1043  Archivo2: 8 12 23 43.
1044  Archivo3: 19 21 87.
1045  Archivo4: 16 36 42 65.
1046  Salida: 1 2 3 4
1047 \layout Standard
1048
1049 Archivo1: 9 34.
1050  Archivo2: 8 12 23 43.
1051  Archivo3: 19 21 87.
1052  Archivo4: 16 36 42 65.
1053  Salida: 1 2 3 4 6
1054 \layout Standard
1055
1056 Archivo1: 9 34.
1057  Archivo2: 12 23 43.
1058  Archivo3: 19 21 87.
1059  Archivo4: 16 36 42 65.
1060  Salida: 1 2 3 4 6 8
1061 \layout Standard
1062
1063 Archivo1: 34.
1064  Archivo2: 12 23 43.
1065  Archivo3: 19 21 87.
1066  Archivo4: 16 36 42 65.
1067  Salida: 1 2 3 4 6 8 9
1068 \layout Standard
1069
1070 Archivo1: 34.
1071  Archivo2: 23 43.
1072  Archivo3: 19 21 87.
1073  Archivo4: 16 36 42 65.
1074  Salida: 1 2 3 4 6 8 9 12
1075 \layout Standard
1076
1077 Archivo1: 34.
1078  Archivo2: 23 43.
1079  Archivo3: 19 21 87.
1080  Archivo4: 36 42 65.
1081  Salida: 1 2 3 4 6 8 9 12 16
1082 \layout Standard
1083
1084 Archivo1: 34.
1085  Archivo2: 23 43.
1086  Archivo3: 21 87.
1087  Archivo4: 36 42 65.
1088  Salida: 1 2 3 4 6 8 9 12 16 19
1089 \layout Standard
1090
1091 Archivo1: 34.
1092  Archivo2: 23 43.
1093  Archivo3: 87.
1094  Archivo4: 36 42 65.
1095  Salida: 1 2 3 4 6 8 9 12 16 19 21
1096 \layout Standard
1097
1098 Archivo1: 34.
1099  Archivo2: 43.
1100  Archivo3: 87.
1101  Archivo4: 36 42 65.
1102  Salida: 1 2 3 4 6 8 9 12 16 19 21 23
1103 \layout Standard
1104
1105 Archivo1:.
1106  Archivo2: 43.
1107  Archivo3: 87.
1108  Archivo4: 36 42 65.
1109  Salida: 1 2 3 4 6 8 9 12 16 19 21 23 34
1110 \layout Standard
1111
1112 Archivo1:.
1113  Archivo2: 43.
1114  Archivo3: 87.
1115  Archivo4: 42 65.
1116  Salida: 1 2 3 4 6 8 9 12 16 19 21 23 34 36
1117 \layout Standard
1118
1119 Archivo1:.
1120  Archivo2: 43.
1121  Archivo3: 87.
1122  Archivo4: 65.
1123  Salida: 1 2 3 4 6 8 9 12 16 19 21 23 34 36 42
1124 \layout Standard
1125
1126 Archivo1:.
1127  Archivo2:.
1128  Archivo3: 87.
1129  Archivo4: 65.
1130  Salida: 1 2 3 4 6 8 9 12 16 19 21 23 34 36 42 43
1131 \layout Standard
1132
1133 Archivo1:.
1134  Archivo2:.
1135  Archivo3: 87.
1136  Archivo4:.
1137  Salida: 1 2 3 4 6 8 9 12 16 19 21 23 34 36 42 43 65
1138 \layout Standard
1139
1140 Archivo1:.
1141  Archivo2:.
1142  Archivo3:.
1143  Archivo4:.
1144  Salida: 1 2 3 4 6 8 9 12 16 19 21 23 34 36 42 43 65 87
1145 \layout Paragraph
1146
1147 Fin
1148 \layout Standard
1149
1150 Finalmente, tengo en el archivo de salida el archivo original ordenado.
1151 \layout Section
1152
1153 Alcance
1154 \layout Standard
1155
1156 El algoritmo de ordenamiento es completamente genérico, ya que recibe un
1157  puntero void como registro, su tamaño (para poder manipularlo sin conocer
1158  su tipo) y una función de comparación, para poder comparar dos registros
1159  (sin saber su tipo) a través de una relación de orden (descripta por dicha
1160  función).
1161 \layout Section
1162
1163 Decisiones de diseño.
1164 \layout Standard
1165
1166 El algoritmo se eligió en base a una serie de razones y cuenta con una serie
1167  de ventajas y desventajas.
1168 \layout Itemize
1169
1170 El algoritmo es simple, tanto teóricamente como para implementar.
1171 \layout Itemize
1172
1173 Tiene la desventaja de que puede llegar a usar muchos archivos temporales
1174  y todos abiertos al mismo tiempo, pero considerando que el sistema operativo
1175  en el que se utiliza suele manejar bien grandes cantidades de archivos
1176  no es una desventaja importante.
1177 \layout Itemize
1178
1179 Al usar un buffer intermedio, se puede controlar muy bien la cantidad de
1180  memoria que utiliza y experimentar con distintos valores para analizar
1181  los resultados.
1182 \layout Itemize
1183
1184 Necesita sólo la misma cantidad de espacio libre en disco que la cantidad
1185  de espacio que ocupa el archivo a ordenar.
1186  Todos los métodos analizados necesitaban igual o más cantidad de espacio
1187  libre.
1188 \layout Itemize
1189
1190 El buffer ordenado se implementó con un árbol binario debido a que tiene
1191  una buena relación entre velocidad de búsqueda y facilidad de implementación.
1192  Al ser el principal determinante de la velocidad los accesos a disco no
1193  se creyó necesario buscar una alternativa más rápida para mantener el buffer
1194  ordenado en memoria, ya que no cambiaría de forma notable el tiempo total
1195  del algoritmo.
1196  Otras posibilidades hubieran sido cargar todo el buffer en memoria y ordenarlo
1197  posteriormente (dependiendo del algoritmo de ordenamiento a utilizar puede
1198  ser más o menos rápido que el árbol y más o menos complicado de implementar)
1199  o hacer una búsqueda secuencial sobre un buffer desordenado (es más fácil
1200  de implementar pero claramente más lento).
1201  Una posible ventaja notable de leer el buffer primero y luego ordenarlo
1202  en memoria es que se necesita un sólo acceso al disco para llenar el buffer,
1203  mientras que al obtener uno a uno los valores puede generar muchos accesos
1204  a disco.
1205  Esto no debería ser muy notable ya que las funciones de acceso a archivos
1206  de la biblioteca estándar de C poseen un buffer interno, por lo que los
1207  accesos a disco probablemente sea muy poco aún cuando se obtienen uno a
1208  uno.
1209 \layout Section
1210
1211 Conclusiones
1212 \layout Standard
1213
1214 Luego de terminar con todo los requerimientos del TP, nos pusimos a tratar
1215  de realizar las comparaciones entre los distintos índices y los tipos de
1216  archivo.
1217  En un primer momento se trato de hacerse midiendo tiempos, pero al no poseer
1218  ANSI C funciones de tiempo con suficiente precisión no se pudo obtener
1219  ninguna conclusión relevante.
1220 \layout Standard
1221
1222 Fue entonces que decidimos hacer una comparativa basada en el uso del programa
1223  modificando los parametros de carga.
1224  Lo que hicimos fue para cada archivo (articulos y facturas) probar utilizar
1225  la clave primaria con los tres tipos de arboles y luego navegar por los
1226  menúes del programa realizando operaciones de consultas, busquedas, etc
1227  a fin de ver si se notaba diferencia.
1228  Este útimo análisis no es del todo objetivo, pero nos dio pié para realizar
1229  una charla por IRC donde discutimos nuestra experiencia con cada tipo de
1230  índice.
1231 \layout Standard
1232
1233 La conclusión a que llegamos es que para el archivo de artículos, que es
1234  de tipo maestro (pues es un archivo que tiene pocas altas y muchas consultas)
1235  sería preferible utilizar un índice primario de tipo B+ ya que nos permite
1236  acceder de manera ordenada de 2 maneras, mediante el índice y tener un
1237  acceso secuencial (ideal para hacer un reporte por ejemplo), y dado que
1238  los artículos permanecerán ordenados los reportes saldrán de la misma manera.
1239 \layout Standard
1240
1241 En cambio para las facturas sería mejor tener un índice B o B*, ya que es
1242  un archivo de transacciónes, donde se suponen que las altas son mayores
1243  que las consultas (esperamos poder vender mucho!).
1244  La ventaja del B y B* es que la inserción es más simple, requiere de un
1245  menor movimiento de registros a la hora de agregar, ya que no es necesario
1246  que en el archivo de datos estos queden ordenados, pudiendo quedar en cualquier
1247  orden fisicamente, aún estando en el mismo bloque.
1248  Esta forma de organizarla obviamente no es para nada útil si necesitaramos
1249  por alguna razón acceder secuencialmente por clave primaria, ya que deberiamos
1250  estar saltando por todo el archivo para poder hacerlo.
1251 \layout Standard
1252
1253 No hemos encontrado muchas razones para decidirnos por B o B*, y que nuestra
1254  implementación es la misma salvando por el insertar, que en el caso del
1255  B* hace todas las rotaciones posibles antes de hacer un split, cosa que
1256  puede beneficiar ya que la creación de nodos es menor, pero para las cantidades
1257  de datos manejados no vemos que influya mucho.
1258 \the_end