home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / postgres / postgre2.z / postgre2 / doc / papers / storage.me < prev   
Encoding:
Text File  |  1992-08-27  |  57.7 KB  |  1,519 lines

  1. .nr tp 12
  2. .nr sp 12
  3. .nr pp 11
  4. .nr fp 10
  5. .sz \n(pp
  6. .fo ''%''
  7. .(l C
  8. .sz \n(sp
  9. .b
  10. THE DESIGN OF THE POSTGRES STORAGE SYSTEM 
  11. .sz \n(pp
  12. .sp 3
  13. .i
  14. Michael Stonebraker
  15. .sp
  16. EECS Department
  17. University of California
  18. Berkeley, Ca., 94720
  19. .sp
  20. .r
  21. .)l
  22. .sp 3
  23. .uh Abstract
  24. .(f
  25. This research was sponsored
  26. by the Navy Electronics Systems Command 
  27. under contract N00039-84-C-0039.
  28. .)f
  29. .pp
  30. This paper presents the design of the storage system for the POSTGRES
  31. data base system under construction at Berkeley.  It is novel in several
  32. ways.  First, the storage manager supports transaction management
  33. but does so without using a conventional write ahead log (WAL).
  34. In fact, there is no code to run at recovery time, and
  35. consequently
  36. recovery from crashes is essentially instantaneous.  Second,
  37. the storage manager allows a user to optionally keep the
  38. entire past history of data base objects by closely integrating
  39. an archival storage system to which historical records are spooled.
  40. Lastly, 
  41. the storage manager is consciously constructed as a collection of asynchronous
  42. processes.  Hence, a large monolithic body of code is avoided
  43. and opportunities for parallelism can be exploited.
  44. The paper concludes with a analysis of the storage system which suggests
  45. that it is performance competitive with WAL systems in many situations.
  46. .sh 1  "INTRODUCTION"
  47. .pp
  48. The POSTGRES storage manager is the collection of modules that provide
  49. transaction management and
  50. access to data base objects.
  51. The design of
  52. these modules was guided by three goals which are discussed
  53. in turn below.
  54. The first goal was to provide
  55. transaction management without the necessity of writing a large amount
  56. of specialized crash recovery code.  Such code is hard to debug, hard to write
  57. and must be error free.  If it fails on an important client of the data manager,
  58. front page news is often the result because the client cannot access his data
  59. base and his business will be adversely affected.  To achieve this goal,
  60. POSTGRES has adopted a novel
  61. storage system in which
  62. no data is ever overwritten; rather all updates are turned into
  63. insertions.  
  64. .pp
  65. The second goal of the storage manager
  66. is to accomodate the historical state of the data base on a 
  67. write-once-read-many (WORM) optical
  68. disk (or other archival medium) in addition to the current state on
  69. an ordinary magnetic disk.
  70. Consequently, we have designed an asynchronous process, called the
  71. .b vacuum
  72. .b cleaner
  73. which moves archival records off magnetic disk and onto an
  74. archival storage system.
  75. .pp
  76. The third goal of the storage system is to take advantage of 
  77. specialized hardware.  In particular, we assume the existence of
  78. non-volatile main memory in some reasonable quantity.  Such memory
  79. can be provide through error correction techniques
  80. and a battery-back-up scheme or from some other
  81. hardware means.  In addition, we expect to have a few low level machine
  82. instructions available for specialized uses to be presently explained.
  83. We also assume that architectures with several processors will
  84. become increasingly popular.  In such an environment, there is an opportunity
  85. to apply multiple processors to running the DBMS where currently
  86. only one is utilized.  This requires the POSTGRES DBMS to be
  87. changed from the monolithic single-flow-of-control architectures
  88. that are prevalent today
  89. to one where there are many asynchronous 
  90. processes concurrently performing
  91. DBMS functions.  Processors with this flavor include the Sequent 
  92. Balance System [SEQU85], the FIREFLY, and SPUR [HILL85].
  93. .pp
  94. The remainder of this paper is organized as follows.  In the next section
  95. we present the design of our magnetic disk storage system.  Then, in 
  96. Section 3 we present the structure and concepts behind our archival 
  97. system.  
  98. Section 4 continues 
  99. with some thoughts on efficient indexes for archival
  100. storage.
  101. Lastly,
  102. Section 5 presents a performance comparison between 
  103. our system and that of
  104. a conventional storage system with a write-ahead
  105. log (WAL) [GRAY78].
  106. .sh 1  "THE MAGNETIC DISK SYSTEM"
  107. .sh 2  "The Transaction System"
  108. .pp
  109. Disk records are changed by data base 
  110. .b transactions, 
  111. each 
  112. of which is given a unique
  113. .b transaction
  114. .b identifier 
  115. (XID).
  116. XIDs are 40 bit unsigned integers that are sequentially assigned 
  117. starting at 1.
  118. At 100 transactions per second (TPS), POSTGRES has sufficient XIDs for
  119. about 320 years of operation.
  120. In addition, the remaining 8 bits 
  121. of a composite 48 bit interaction identifier (IID) is a command
  122. identifier (CID) for each command within a transaction.  Consequently,
  123. a transaction is limited to executing at most 256 commands. 
  124. .pp
  125. In addition there is a 
  126. .b transaction
  127. .b log
  128. which contains 2 bits per transaction indicating its status
  129. as:
  130. .(l
  131. committed
  132. aborted
  133. in progress
  134. .)l
  135. A transaction is 
  136. .b started
  137. by advancing a counter containing the first unassigned
  138. XID and using the current contents as a XID.  The coding of the
  139. log has a default value for a transaction as ``in progress'' so
  140. no specific change to the log need be made at the start of
  141. a transaction.
  142. A transaction is 
  143. .b committed
  144. by changing its status in the log from ``in progress'' to ``committed''
  145. and placing the appropriate disk block of the log 
  146. in stable storage.
  147. Moreover, any data pages that were changed on behalf of the transaction
  148. must also be placed in stable storage.
  149. These pages can either be forced
  150. to disk or moved to stable main memory
  151. if any is available.
  152. Similarly, a transaction is aborted by changing its status from
  153. ``in progress'' to ``aborted''.
  154. .pp
  155. The
  156. .b tail
  157. of the log 
  158. is that portion of the log from the oldest active transaction
  159. up to the present.  The
  160. .b body
  161. of the log is the remainder of the log and transactions in
  162. this portion cannot be ``in progress'' so only 1 bit need be allocated.
  163. The body of the log
  164. occupies a POSTGRES relation
  165. for which a special access method has been built.
  166. This access method places
  167. the status of 65536 transactions on each POSTGRES 
  168. 8K disk block.  At 1 transaction per second, the
  169. body increases in size at a rate of 4 Mbytes per year.
  170. Consequently, 
  171. for light applications, the log for the entire history of operation
  172. is not a large object and
  173. can fit in a sizeable
  174. buffer pool.
  175. Under normal circumstances several 
  176. megabytes of memory will be used for this purpose and the status of all
  177. historical transactions can be readily found without requiring a disk read.
  178. .pp
  179. In heavier applications where the body of the log will not fit in
  180. main memory, POSTGRES applies an optional compression technique.
  181. Since most transactions commit, the
  182. body of the log contains almost all ``commit'' bits.  Hence, POSTGRES has 
  183. an optional bloom filter [SEVR76] for the aborted transactions.  This tactic
  184. compresses  
  185. the buffer space needed for the log by
  186. about a factor of 10.  Hence, the bloom filter for heavy applications should
  187. be accomodatable in main memory.  Again the run-time system need not read
  188. a disk block to ascertain the status of any transaction.
  189. The details of the bloom filter design are presented in [STON86].
  190. .pp
  191. The tail of the log is a small data structure.  If the oldest transaction
  192. started one day ago, then there are about 86,400 transactions in the tail
  193. for each 1 transaction per second processed.  At 2 bits per entry, 
  194. the tail requires 21,600 bytes per transaction per second. 
  195. Hence, it is reasonable to put the tail of the log in stable main memory
  196. since this will save the pages containing the tail of the log from
  197. being forced to disk many times in quick succession as transactions
  198. with similar transaction identifiers commit.
  199. .sh 2  "Relation Storage"
  200. .pp
  201. When a relation is created, a file is allocated to hold the
  202. records of that relation.  Such records have no
  203. prescribed maximum length, so the storage manager is prepared to
  204. process records which cross disk block boundaries.
  205. It does so by allocating continuation records and chaining them together
  206. with a linked list.  Moreover, the order of writing of the disk blocks
  207. of extra long records must be carefully controlled.  The details of this support
  208. for multiblock records are straightforward, and we do not discuss them 
  209. further in this paper.
  210. Initially, POSTGRES is using conventional files provided by the
  211. UNIX operating system; however, we may reassess this decision
  212. when the entire system is operational.  If space in a file is exhausted,
  213. POSTGRES extends the file by some multiple of the 8K page size.
  214. .pp
  215. If a user wishes the records in a relation 
  216. to be approximately clustered
  217. on the value of a designated field, 
  218. he must declare his intention by indicating the appropriate field
  219. in the following command
  220. .(l
  221. cluster rel-name on {(field-name using operator)}
  222. .)l
  223. POSTGRES will
  224. attempt to keep the records approximately in sort order on
  225. the field name(s) indicated using
  226. the specified operator(s) to define the linear ordering.  This will allow
  227. clustering secondary indexes to be created as 
  228. in [ASTR76].  
  229. .pp
  230. Each disk record has a bit mask indicating which fields are non-null, and
  231. only these fields are actually stored.  In addition, because 
  232. the magnetic disk storage system 
  233. is fundamentally a versioning system, each record contains
  234. an additional
  235. 8 fields:
  236. .(l
  237. OID    a system-assigned unique record identifier
  238. Xmin    the transaction identifier of the interaction inserting the record
  239. Tmin    the commit time of Xmin (the time at which the record became valid)
  240. Cmin    the command identifier of the interaction inserting the record
  241. Xmax    the transaction identifier of the interaction deleting the record
  242. Tmax    the commit time of Xmax (the time at which the record stopped being valid)
  243. Cmax    the command identifier of the interaction deleting the record
  244. PTR    a forward pointer
  245. .)l
  246. When a record is inserted it is assigned a unique OID, and
  247. Xmin and Cmin are set to the 
  248. identity of the current interaction. 
  249. the remaining five fields are left blank.
  250. When 
  251. a record is updated, 
  252. two operations take place.  
  253. First, Xmax and Cmax are set to 
  254. the identity of the current interaction
  255. in the record being replaced to
  256. indicate that it is no longer valid.  
  257. Second, a new record is inserted
  258. into the data base with the proposed replacement values for 
  259. the data fields.  Moreover, OID
  260. is set to the OID of the record being replaced, and
  261. Xmin and Cmin
  262. are set to the identity of the current interaction.  
  263. When a record is deleted, Xmax and Cmax are set to the identity of 
  264. the current interaction in the record to be deleted.
  265. .pp
  266. When a record is updated, the new version usually 
  267. differs from the old version in only a few fields.
  268. In order to avoid the space cost of a complete new record, the following
  269. compression technique has been adopted.
  270. The initial record is stored uncompressed and called the
  271. .b anchor
  272. .b point. 
  273. Then, the updated record is differenced against the anchor point and
  274. only the actual changes are 
  275. stored.  
  276. Moreover, PTR is altered on the anchor point
  277. to point to the updated
  278. record, which is called a 
  279. .b delta 
  280. .b record.  
  281. Successive updates generate a one-way linked list of delta records off
  282. an initial anchor point.
  283. Hopefully most delta record are on the same operating system page
  284. as the anchor point since they
  285. will typically be
  286. small objects.
  287. .pp
  288. It
  289. is the expectation that POSTGRES would be used as a local data manager
  290. in a distributed data base system.  Such a distributed system would
  291. be expected to maintain multiple copies of all important POSTGRES objects.  
  292. Recovery from hard crashes, i.e. one for which the disk cannot be 
  293. read, would occur by switching to some other copy of the object.
  294. In a non-distributed system POSTGRES will allow a user to
  295. specify that he wishes a second copy
  296. of specific objects with
  297. the
  298. command:
  299. .(l
  300. mirror rel-name
  301. .)l
  302. Some
  303. operating systems (e.g. VMS [DEC86] and Tandem [BART81]) already support
  304. mirrored files, so special DBMS code will not be necessary in these
  305. environments.
  306. Hopefully, mirrored files will become a standard
  307. operating systems service in most environments
  308. in the future.
  309. .sh 2  "Time Management"
  310. .pp
  311. The POSTGRES query language, POSTQUEL allows a user to request the salary
  312. of Mike using the following syntax.
  313. .(l
  314. retrieve (EMP.salary) where EMP.name = ``Mike''
  315. .)l
  316. To support 
  317. access to historical tuples, the query language is extended as follows:
  318. .(l
  319. retrieve (EMP.salary) using EMP[T] where EMP.name = ``Mike''
  320. .)l
  321. The scope of this command is the EMP relation as of a specific
  322. time, T, and Mike's salary will be found as of that time.  
  323. A variety of formats for T will be allowed, and a conversion routine
  324. will be called to convert times to the 32 bit unsigned integers
  325. used internally.
  326. POSTGRES constructs a query plan to find qualifying 
  327. records in the normal fashion.  
  328. However, each accessed tuple must be additionally checked 
  329. for validity
  330. at the time desired in the user's query.
  331. In general, a record is 
  332. .b valid
  333. .b at
  334. .b time
  335. .b T
  336. if the following is true:
  337. .(l
  338. Tmin < T and Xmin is a committed transaction and either:
  339.    Xmax is not a committed transaction or
  340.    Xmax is null  or
  341.    Tmax > T 
  342. .)l
  343. In fact, to allow a user to read uncommitted records that
  344. were written by a different command within his transaction, the actual
  345. test for validity is the following more complex condition.
  346. .(l
  347. Xmin = my-transaction and Cmin != my-command and T = ``now''
  348.         or
  349. Tmin < T and Xmin is a committed transaction and either:
  350.    (Xmax is not a committed transaction and Xmax != my-transaction) or 
  351.    (Xmax = my-transaction and Cmax = my-command) or
  352.     Xmax is null  or
  353.     Tmax > T or
  354. .)l
  355. If T
  356. is not specified, then T = ``now'' is the default value, and  
  357. a record is valid at time, ``now'' if
  358. .(l
  359. Xmin = my-transaction and Cmin != my-command
  360.        or
  361. Xmin is a committed transaction and either
  362.    (Xmax is not a committed transaction and Xmax != my-transaction) or
  363.    (Xmax = my-transaction and Cmax = my-command) or
  364.    Xmax is null 
  365. .)l
  366. .pp
  367. More
  368. generally, Mike's salary history over a range of times can be retrieved by:
  369. .(l
  370. retrieve (EMP.Tmin, EMP.Tmax, EMP.salary) 
  371. using EMP[T1,T2] where EMP.name = ``Mike''
  372. .)l
  373. This command will find all salaries for Mike along with their starting and
  374. ending times as long as the salary is valid at some point in the interval,
  375. [T1, T2].  In general,
  376. a record is 
  377. .b valid
  378. .b in
  379. .b the
  380. .b interval
  381. .b [T1,T2]
  382. if:
  383. .(l
  384. Xmin = my-transaction and Cmin != my-command and T2 >= ``now''
  385.         or
  386. Tmin < T2 and Xmin is a committed transaction and either:
  387.    (Xmax is not a committed transaction and Xmax != my-transaction) or 
  388.    (Xmax = my-transaction and Cmax = my-command) or
  389.    Xmax is null  or
  390.    Tmax > T1 
  391. .)l
  392. Either T1 or T2 can be omitted and the defaults are respectively T1 = 0
  393. and T2 = +infinity
  394. .pp
  395. Special programs (such as debuggers) may want to be 
  396. able to access uncommitted records.
  397. To facilitate such access, we define a second 
  398. specification for each relation, for example:
  399. .(l
  400. retrieve (EMP.salary) using all-EMP[T] where EMP.name = ``Mike''
  401. .)l
  402. An EMP record is in all-EMP at time T if
  403. .(l
  404. Tmin < T and (Tmax > T or Tmax = null)
  405. .)l
  406. Intuitively, all-EMP[T] is the set of all tuples
  407. committed, aborted or in-progress at time T.
  408. .pp
  409. Each accessed magnetic disk record must have one of the above tests performed.
  410. Although each test is potentially CPU and I/O 
  411. intensive, we are not overly concerned
  412. with CPU resources because we do not expect the CPU 
  413. to be a significant bottleneck in next generation systems.  This point
  414. is discussed further in Section 5.  Moreover,
  415. the CPU portion of these 
  416. tests can be easily committed to custom logic or microcode or
  417. even a co-processor if it becomes a bottleneck.
  418. .pp
  419. There will be little or no I/O associated with accessing the status of
  420. any transaction, since we expect the transaction log (or its associated
  421. bloom filter) to be in main memory.  We turn in the next subsection to 
  422. avoiding I/O when evaluating the remainder of the above predicates.
  423. .sh 2  "Concurrency Control and Timestamp Management"
  424. .pp
  425. It would be natural to assign a timestamp to a transaction
  426. at the time it is started and then
  427. fill in the timestamp field of each record as
  428. it is updated by the transaction.  
  429. Unfortunately, this would require POSTGRES to process transactions
  430. logically in timestamp order to avoid anomolous behavior.
  431. This is equivalent to requiring POSTGRES to use a concurrency
  432. control scheme based on timestamp ordering (e.g. [BERN80].  Since
  433. simulation results have shown the superiority of conventional locking [AGRA85],
  434. POSTGRES uses instead
  435. a standard two-phase locking policy which
  436. is implemented by
  437. a conventional main memory lock table.  
  438. .pp
  439. Therefore, 
  440. Tmin and Tmax must be set 
  441. to the commit
  442. time of each transaction (which is the time at which 
  443. updates logically take place)
  444. in order to avoid anomolous behavior.  
  445. Since the commit time of a transaction
  446. is not known in advance, Tmin and Tmax cannot be assigned
  447. values at
  448. the
  449. time that a record is written.  
  450. .pp
  451. We use the following technique to fill in these fields asynchronously. 
  452. POSTGRES contains a TIME relation in which the
  453. commit time of each transaction is stored.  Since timestamps are
  454. 32 bit unsigned integers, byte positions 4*j through 4*j + 3 are
  455. reserved for the commit time of transaction j.
  456. At the time a transaction commits,
  457. it reads the current clock time and stores it in the appropriate slot of 
  458. TIME.  The tail of the TIME relation can be stored in stable main memory
  459. to avoid the I/O that this update would otherwise entail.
  460. .pp
  461. Moreover, each relation in a POSTGRES data base is tagged at the
  462. time it is created with one of the following three designations:
  463.  
  464. no archive:  This indicates that no historical 
  465. access to relations is required. 
  466.  
  467. light archive:  This indicates that an archive is desired 
  468. but little access to it 
  469.                     is expected. 
  470.  
  471. heavy archive:  This indicates that heavy use will be made of the archive.
  472.  
  473. For relations with ``no archive'' status, Tmin and Tmax are never
  474. filled in, since access to historical tuples is never required.
  475. For such relations, only POSTQUEL commands specified for 
  476. T = ``now'' can be processed.
  477. The validity check for T = ``now''
  478. requires access only to the POSTGRES LOG relation which
  479. should be contained in the buffer pool.  Hence, the test consumes no
  480. I/O resources.
  481. .pp
  482. If ``light archive'' is specified, then access to historical tuples
  483. is allowed.  
  484. Whenever Tmin or Tmax must be compared to some specific
  485. value, the commit time of the appropriate transaction is retrieved from
  486. the TIME relation to make the comparison.  Access to historical
  487. records will be slowed in the ``light archive'' situation by this requirement
  488. to perform an I/O to the TIME relation for each timestamp value 
  489. required.
  490. This 
  491. overhead will only be tolerable
  492. if archival records are accessed a very small
  493. number of times in their lifetime (about 2-3). 
  494. .pp
  495. In the ``heavy archive'' condition, the run time system must look up the
  496. commit time of a transaction as in the ``light archive'' case.  However,
  497. it then writes the value found into Tmin or Tmax, thereby turning the read of
  498. a historical record into a write.  Any subsequent accesses to the
  499. record will then be validatable without the extra access to the TIME
  500. relation.
  501. Hence, the first access to an archive record will be costly in the 
  502. ``heavy archive'' case, but subsequent ones will will incur no extra
  503. overhead.
  504. .pp
  505. In addition, we expect to explore the utility of running another system
  506. demon in background to asynchronously fill in timestamps for ``heavy 
  507. archive'' relations.
  508. .sh 2  "Record Access"
  509. .pp
  510. Records can be accessed by a sequential scan of a relation.  In this
  511. case, pages of the appropriate file
  512. are read in a POSTGRES determined order.  
  513. Each page contains a pointer to the next and the previous logical page; hence
  514. POSTGRES can scan a relation by following the forward linked list.  The
  515. reverse pointers are required because POSTGRES can execute query plans either
  516. forward or backward.
  517. Additionally, on each page there is a line
  518. table as in [STON76]
  519. containing pointers to the 
  520. starting byte of each anchor point record on that page.
  521. .pp
  522. Once an anchor point is located, the delta records linked to it
  523. can be constructed by
  524. following PTR and decompressing the data fields.
  525. Although decompression is a CPU intensive task, we feel 
  526. that CPU resources will
  527. not be a bottleneck in future computers as noted earlier.  Also, 
  528. compression and decompression
  529. of records is a task easily committed to microcode or a separate
  530. co-processor.
  531. .pp
  532. An arbitrary number of secondary indexes can be constructed for any
  533. base relation.  
  534. Each index is maintained by an 
  535. .b access
  536. .b method.
  537. and provides keyed access on a field or a collection of fields.  Each
  538. access method must provide all the procedures for the POSTGRES defined
  539. abstraction for access methods.  These include get-record-by-key,
  540. insert-record, delete-record, etc.
  541. The POSTGRES run time system will call the various routines of the
  542. appropriate access method when needed during query processing.  
  543. .pp
  544. Each access method supports efficient access for a collection of
  545. operators as noted in [STON86a].  For example, B-trees can provide
  546. fast access for any of the operators:
  547. .(l
  548. {=, <=, <, >, >=}
  549. .)l
  550. Since each access method may be required to work for various data types,
  551. the collection of operators that an access methods will use for a specific
  552. data type must be 
  553. .b registered
  554. as an
  555. .b operator
  556. .b class.
  557. Consequently, the syntax for index creation is:
  558. .(l
  559. index on rel-name is index-name ({key-i with operator-class-i})
  560. using access-method-name and performance-parameters
  561. .)l
  562. The performance-parameters specify the fill-factor to be used
  563. when loading the pages of the index, and the minimum and maximum number of
  564. pages to allocate.
  565. The following example specifies a B-tree index on a combined key consisting
  566. of an integer and a floating point number.
  567. .(l
  568. index on EMP is EMP-INDEX (age with integer-ops, salary with float-ops)
  569. using B-tree and fill-factor = .8
  570. .)l
  571. .pp
  572. The run-time system handles secondary indexes in a somewhat unusual
  573. way.  When a record is inserted, an anchor point is
  574. constructed for the record along with index entries 
  575. for each secondary index.  
  576. Each index record contains a key(s) plus 
  577. a pointer to an entry in the line table on the
  578. page where the indexed record resides.  
  579. This line table entry in turn
  580. points to the byte-offset of the actual record.  This single level of
  581. indirection allows anchor points to be moved on a data page without
  582. requiring maintenance of secondary indexes.
  583. .pp
  584. When 
  585. an existing record is updated, a delta record is constructed and chained
  586. onto the appropriate anchor record.  If no indexed field has been modified,
  587. then no maintenance of secondary indexes is required.  If an indexed field
  588. changed, then an entry is added to the appropriate index containing
  589. the new key(s) and a pointer to the anchor record.  There are no pointers
  590. in secondary indexes directly to delta records.
  591. Consequently, a delta record can only
  592. be accessed by obtaining its corresponding anchor point and chaining
  593. forward. 
  594. .pp
  595. The POSTGRES query optimizer constructs plans
  596. which may specify scanning portions of various secondary indexes.
  597. The run time code to support this function
  598. is relatively conventional except for the fact that 
  599. each secondary index entry points to 
  600. an anchor point and a chain of delta records, all of which must be 
  601. inspected.  Valid records that actually match the key in the index are
  602. then returned to higher level software.
  603. .pp
  604. Use of this technique guarantees that record updates only
  605. generate I/O activity in those secondary indexes whose keys change.
  606. Since updates to keyed fields are relatively uncommon, this 
  607. ensures that few insertions must be performed in the secondary indexes.
  608. .pp
  609. Some secondary indexes which are
  610. hierarchical in nature require disk pages to be placed in stable storage
  611. in a particular order (e.g. from leaf to root for page splits in B+-trees).
  612. POSTGRES will provide a low level command 
  613. .(l
  614. order block-1 block-2
  615. .)l
  616. to support such required orderings.  This command is in addition to
  617. the required 
  618. .b pin 
  619. and
  620. .b unpin 
  621. commands to the buffer manager.
  622. .sh 1  "THE ARCHIVAL SYSTEM"
  623. .sh 2  "Vacuuming the Disk"
  624. .pp
  625. An asynchronous demon 
  626. is responsible for sweeping records which
  627. are no longer valid to the archive.
  628. This demon, called the 
  629. .b vacuum 
  630. .b cleaner,
  631. is given instructions using the following command:
  632. .(l
  633. vacuum rel-name after T
  634. .)l
  635. Here 
  636. T is a time relative to ``now''.  For example, 
  637. the following vacuum command specifies vacuuming records
  638. over 30 days old:
  639. .(l
  640. vacuum EMP after ``30 days'' 
  641. .)l
  642. The vacuum cleaner
  643. finds candidate records for archiving which satisfy one of the
  644. following conditions:
  645. .(l
  646. Xmax is non empty and is a committed transaction and ``now'' - Tmax >= T
  647. Xmax is non empty and is an aborted transaction
  648. Xmin is non empty and is an aborted transaction
  649. .)l
  650. In the second and third cases, the vacuum cleaner simply
  651. reclaims the space occupied by such records.  In the first
  652. case, a record must be copied to the archive unless ``no-archive''
  653. status is set for this relation.
  654. Additionally, if ``heavy-archive'' is specified, Tmin and Tmax must be
  655. filled in by the vacuum cleaner during archiving if they have not already
  656. been given values during a previous access.
  657. Moreover, if an anchor point and several delta records 
  658. can be swept together, the vacuuming process will be more efficient.
  659. Hence, the vacuum cleaner will generally sweep a chain of several
  660. records
  661. to the archive at one time.
  662. .pp
  663. This sweeping must be done very carefully so that no
  664. data is irrecoverably lost.  
  665. First we discuss the format of the archival medium, then we turn to
  666. the sweeping algorithm and a discussion of its cost.
  667. .sh 2  "The Archival Medium"
  668. .pp
  669. The archival storage system is compatible with WORM devices, but
  670. is not restricted to such systems.  We are building a conventional 
  671. extent-based file system on the archive, and each relation
  672. is allocated to a single file.  Space is allocated in large
  673. extents and the next one is allocated when the current one is
  674. exhausted.  The space allocation
  675. map for the archive is kept in a magnetic disk relation.  
  676. Hence, it is possible, albeit very costly, to sequentially scan the
  677. historical version of a relation.
  678. .pp
  679. Moreover, there are an arbitrary number of secondary indexes 
  680. for each relation in the archive.  Since historical accessing patterns may
  681. be different than accessing patterns for current data, we do not
  682. restrict the archive indexes to be the same as those for the magnetic disk
  683. data base.  Hence, archive indexes must be
  684. explicitly created using the following
  685. extension of the indexing command:
  686. .(l
  687. index on {archive} rel-name is index-name ({key-i with operator-class-i})
  688. using access-method-name and performance-parameters
  689. .)l
  690. Indexes for archive relations are normally stored on magnetic disk.  However,
  691. since they may become very large, we will discuss mechanisms in the next section
  692. to
  693. support archive indexes that are partly on the archive medium.
  694. .pp
  695. The anchor point and a collection of
  696. delta records are concatenated and written
  697. to the archive as a single variable length record.
  698. Again secondary index records must be inserted for any indexes defined
  699. for the archive relation.  
  700. An index record is generated for the anchor point for each archive secondary
  701. index.  Moreover, an index record must be constructed for each delta record
  702. in which a secondary key has been changed.
  703. .pp
  704. Since the access paths to the portion of a relation on the archive
  705. may be different than the access paths to the portion on magnetic disk,
  706. the query optimizer must generate two plans for any query that requests
  707. historical data.
  708. Of course, these plans can 
  709. be executed in parallel if multiple
  710. processors are available.
  711. In addition, we are studying the decomposition of each of these two
  712. query plans into additional parallel pieces.
  713. A report on this subject is in preparation [BHID87].
  714. .sh 2  "The Vacuum Process"
  715. .pp
  716. Vacuuming is done in three phases, namely:
  717. .(l
  718. phase 1:  write an archive record and its associated index records
  719. phase 2:  write a new anchor point in the current data base
  720. phase 3:  reclaim the space occupied by the old anchor point and its delta 
  721.              records
  722. .)l
  723. If a crash occurs while the vacuum cleaner
  724. is writing the historical record in phase 1,
  725. then the data still exists in the magnetic disk data base and will be
  726. revacuumed again at some later time.  If the historical
  727. record has been written but not the associated indexes, then 
  728. the archive will have a record which is reachable only through
  729. a sequential scan.
  730. If a crash occurs after
  731. some index 
  732. records have been written, then
  733. it will be possible for the same record 
  734. to be accessed in a magnetic disk relation and in an
  735. archive relation.  In either case, the 
  736. duplicate record will consume system resources;
  737. however, there are no other
  738. adverse consequences because POSTGRES is a relational
  739. system and removes duplicate records during processing.   
  740. .pp
  741. When the record is safely stored on the archive and indexed appropriately,
  742. the second phase of vacuuming can occur.
  743. This phase entails computing a new anchor point for the magnetic disk
  744. relation and
  745. adding new index records for it.
  746. This anchor point is found by starting at the old
  747. anchor point and calculating the value of the last delta that satisfies
  748. .(l
  749. ``now'' - Tmax >= T
  750. .)l 
  751. by
  752. moving forward through the linked list.  The appropriate values
  753. are inserted into the magnetic disk relation,
  754. and index records are
  755. inserted into all appropriate index.  When this phase is complete,
  756. the new anchor point record is accessible directly from secondary indexes
  757. as
  758. well as by chaining forward from the old anchor point.
  759. Again, if there is a crash during this phase
  760. a
  761. record may be
  762. accessible twice in some future queries, resulting in 
  763. additional overhead
  764. but no other consequences.  
  765. .pp
  766. The last phase
  767. of the vacuum process is to remove the original anchor point
  768. followed by all delta records and then to delete all index
  769. records that pointed to this deleted anchor point.
  770. If there is a crash
  771. during this phase, index records may exist that do not point to a
  772. correct data record.  Since the run-time system must already check
  773. that data records are valid and have the key that the appropriate
  774. index record expects them to have,
  775. this situation can be checked using the same mechanism.
  776. .pp
  777. Whenever there is a failure, the vacuum cleaner is simply restarted
  778. after the failure is repaired.  It will
  779. re-vacuum any record that was in progress 
  780. at some later time. 
  781. If the crash occurred during phase 3, the vacuum cleaner could be
  782. smart enough to realize that the record was already safely vacuumed.
  783. However, the cost of this checking is probably not worthwhile.  
  784. Consequently, failures will result in a slow accumulation of
  785. extra records in the archive.  We are depending on crashes to be
  786. infrequent enough that this is not a serious concern.
  787. .pp
  788. We now turn to the cost of the vacuum cleaner.
  789. .sh 2  "Vacuuming Cost"
  790. .pp
  791. We examine two different vacuuming situations.  In the
  792. first 
  793. case we assume that a record is inserted, updated
  794. K times and then deleted.
  795. The whole chain of records from insertion to deletion is vacuumed at
  796. once.  In the second case, we assume that the
  797. vacuum is run after K updates,
  798. and a new anchor record must be inserted.  In both cases, we assume that
  799. there are Z secondary indexes for both the archive
  800. and magnetic disk relation, that no key changes 
  801. are made during these K updates, and that an anchor point 
  802. and all its delta records
  803. reside on the same page.
  804. Table 1 indicates the vacuum cost for each case.
  805. .(z
  806. .hl
  807. .(c
  808. .TS
  809. c c c c
  810. l l l l.
  811.     whole chain    K updates    
  812.  
  813. archive-writes    1+Z    1+Z    
  814. disk-reads    1    1
  815. disk-writes    1+Z    1+Z
  816.  
  817. .TE
  818. .)c
  819. .sp
  820. .ce
  821. I/O Counts for Vacuuming 
  822. .ce 
  823. Table 1
  824. .hl
  825. .)z
  826. Notice that vacuuming consumes a constant cost.  This rather surprising
  827. conclusion reflects the fact that a new anchor record can be inserted
  828. on the same page from which the old anchor point is being deleted
  829. without 
  830. requiring the page to be forced to stable memory in between the operations.
  831. Moreover, the new index records can be inserted
  832. on the same page from which the previous entries are deleted 
  833. without an intervening I/O.  Hence,
  834. the cost PER RECORD of the vacuum cleaner decreases as the length of the
  835. chain, K, increases.  As long as an anchor point and several delta 
  836. records are vacuumed
  837. together, the cost should be marginal.
  838. .sh 1  "INDEXING THE ARCHIVE"
  839. .sh 2  "Magnetic Disk Indexes"
  840. .pp
  841. The archive can be indexed by conventional magnetic disk indexes.
  842. For example, one could construct a 
  843. salary index on the archive which would be helpful in answering
  844. queries of the form:
  845. .(l
  846. retrieve (EMP.name) using EMP [,] where EMP.salary = 10000
  847. .)l
  848. However, to provide fast access for queries which restrict the
  849. historical scope of interest, e.g:
  850. .(l
  851. retrieve (EMP.name) using EMP [1/1/87,] where EMP.salary = 10000
  852. .)l
  853. a standard salary index will not be of much use because the index
  854. will return all historical salaries of the correct size whereas the
  855. query only requested a small subset.  Consequently, in addition to
  856. conventional indexes, we expect time-oriented indexes to be
  857. especially useful for archive relations.
  858. Hence, the two fields, Tmin and Tmax, are stored in the archive as
  859. a single field, I, of type 
  860. .b interval.
  861. An R-tree access method [GUTM84] can be constructed to provide
  862. an index on this interval field.  The operators for which an R-tree
  863. can provide fast access include "overlaps" and "contained-in".  Hence,
  864. if these operators are written for the interval data type, an R-tree
  865. can be constructed for the EMP relation as follows:
  866. .(l 
  867. index on archive EMP is EMP-INDEX (I with interval-ops)
  868. using R-tree and fill-factor = .8
  869. .)l
  870. This index can support fast access to the historical state of the EMP relation
  871. at any point in time or during a particular period.
  872. .pp
  873. To utilize such indexes, the POSTGRES query planner needs to be
  874. slightly modified.
  875. Note that POSTGRES need only run a query on an archive relation if
  876. the scope of the relation includes some historical records,  Hence,
  877. the query for an archive relation must be of the form:
  878. .(l
  879.   ...using EMP[T]
  880. .)l
  881. or
  882. .(l
  883.  ...using EMP[T1,T2]
  884. .)l
  885. The planner converts the first construct into:
  886. .(l
  887.   ...where T contained-in EMP.I
  888. .)l
  889. and the second into:
  890. .(l
  891.   ...where interval(T1,T2) overlaps EMP.I
  892. .)l
  893. Since all records in the archive are guaranteed to be
  894. valid, these two qualifications
  895. can replace all the low level code 
  896. that checks for record validity on the magnetic disk 
  897. described in Section 2.3.  With this
  898. modification,
  899. the query optimizer can use the added qualification to provide a
  900. fast access path through an interval index if one exists.
  901. .pp
  902. Moreover, we expect combined indexes on the interval field along
  903. with some data value to be very attractive, e.g:
  904. .(l
  905. index on archive EMP is EMP-INDEX 
  906. (I with interval-ops, salary with float-ops)
  907. using R-tree and fill-factor = .8
  908. .)l
  909. Since an R-tree is a multidimensional
  910. index, the above index supports intervals 
  911. which exist in a two dimensional space
  912. of time and salaries.  A query such as:
  913. .(l
  914. retrieve (EMP.name) using EMP[T1,T2] where EMP.salary = 10000
  915. .)l
  916. will be turned into:
  917. .(l
  918. retrieve (EMP.name) where EMP.salary = 10000 
  919.                          and interval(T1,T2) overlaps EMP.I
  920. .)l
  921. The two clauses of the qualification define another interval in two dimensions
  922. and conventional R-tree processing of the interval can be performed to
  923. use both qualifications to
  924. advantage.  
  925. .pp
  926. Although data records will be added to the archive at the convenience of the
  927. vacuum cleaner, records will be generally inserted in ascending
  928. time order.  Hence, the poor performance reported in [ROUS85]
  929. for R-trees should be averted by the nearly sorted order in which 
  930. the records will be inserted.  Performance tests to ascertain this
  931. speculation are planned.
  932. We now turn to a discussion of R-tree indexes that are partly on both
  933. magnetic and archival mediums.
  934. .sh 2  "Combined Media Indexes"
  935. .pp  
  936. We begin with a small space calculation to illustrate the
  937. need for indexes that use both media.  
  938. Suppose a relation exists with 10**6 tuples and each tuple
  939. is modified 30 times during the lifetime of the application.
  940. Suppose there are two secondary indexes
  941. for both the archive and the disk relation and updates never
  942. change the values of key fields.  
  943. Moreover, suppose
  944. vacuuming occurs after the 5th delta record is written,  so 
  945. there are an average of 3 delta records for each anchor point.
  946. Assume that anchor points
  947. consume 200 bytes, delta records consume 40 bytes,
  948. and index keys are 10 bytes long.  
  949. .pp
  950. With these assumptions, the
  951. sizes in bytes of each kind of object are indicated in Table 2.
  952. .(z
  953. .hl
  954. .(c
  955. .TS
  956. c c
  957. l l.
  958. object    mbytes 
  959.  
  960. disk relation anchor points    200
  961. deltas    120
  962. secondary indexes    28
  963.  
  964. archive    2160
  965. archive indexes    168
  966. .TE
  967. .)c
  968. .sp
  969. .ce
  970. Sizes of the Various Objects
  971. .ce
  972. Table 2
  973. .hl
  974. .)z
  975. Clearly, 10**6 records will consume 200 mbytes while 3 x 10**6 delta
  976. records will require 120 mbytes.  Each index record is assumed to require a four
  977. byte pointer in addition to the 10 byte key; hence each of the two indexes
  978. will take up 14 mbytes.  
  979. There are 6 anchor point records on the archive for each of the 10**6 
  980. records each concatenated with 4 delta records.  Hence, archive records will
  981. be 360 bytes long, and require 2160 mbytes.  Lastly, there is an
  982. index record for each of the archive anchor points; hence the archive indexes
  983. are 6 times as large as the magnetic disk indexes.
  984. .pp
  985. Two points are evident from Table 2.  First, the archive can become
  986. rather large.  Hence, one should vacuum infrequently to cut down on the
  987. number of anchor points that occur in the archive.  Moreover, it might
  988. be desirable to differentially code the anchor points to save space.  
  989. The second point to notice is that the archive indexes consume a large
  990. amount of space on magnetic disk.  if the target relation had
  991. three indexes instead of two, the archive indexes would consume a greater
  992. amount
  993. of space than the magnetic disk relation.
  994. Hence, we explore in this section data structures that allow part of the
  995. index to migrate to the archive.
  996. Although we could alternatively consider index structures that are
  997. entirely on the archive, such as those proposed in [VITT85], we
  998. believe that combined media structures will substantially outperform
  999. structures restricted to the archive.  We plan performance comparisons
  1000. to demonstrate the validity of this hypothesis.
  1001. .pp
  1002. Consider an R-tree storage structure in which each pointer in a non-leaf
  1003. node of the R-tree is
  1004. distinguished to be either a magnetic disk page pointer or an archive 
  1005. page pointer.  If
  1006. pointers are 32 bits, then we can use the high-order bit for this purpose
  1007. thereby allowing the remaining 31 bits to specify 2**31 pages on magnetic
  1008. disk or archive storage.  If pages are 8K bytes, then the
  1009. maximum size of an archive
  1010. index is 2**44 bytes (about 1.75 x 10**13 bytes), clearly adequate for almost
  1011. any application.  Moreover, the leaf level pages of the R-tree contain
  1012. key values and pointers to associated data records.  These data pointers
  1013. can be 48 bytes long, thereby allowing the data file corresponding to
  1014. a single historical relation to be 2**48 bytes long (about 3.0 x 10**14
  1015. bytes), again adequate for most applications.
  1016. .pp
  1017. We assume that the archive may be a write-once-read-many (WORM) device
  1018. that allows pages to be initially written but then does not allow any
  1019. overwrites of the page.  With this assumption, records
  1020. can only be dynamically added to pages
  1021. .bp
  1022. that reside on
  1023. magnetic disk.  Table 3 suggests two 
  1024. sensible strategies
  1025. for the placement of new records
  1026. when they are not entirely contained inside some 
  1027. R-tree index region corresponding
  1028. to a magnetic disk page.
  1029. .(z
  1030. .hl
  1031. .(c
  1032. .TS
  1033. c c
  1034. l l.
  1035. P1   allocate to the region which has to be expanded the least
  1036. P2   allocate to the region whose maimum time has to be expanded the least
  1037. .TE
  1038. .)c
  1039. .sp
  1040. .ce
  1041. Record Insertion Strategies
  1042. .ce
  1043. Table 3
  1044. .hl
  1045. .)z
  1046. .pp
  1047. Moreover, we assume that any page that
  1048. resides on the archive contains pointers that in turn point only
  1049. to pages on the archive.  This avoids having to contend with 
  1050. updating an archive page which contains a pointer to a magnetic disk 
  1051. page that splits.  
  1052. .pp
  1053. Pages in an R-tree can be moved from magnetic disk to the archive 
  1054. as long as they contain only archive page pointers.  Once a page moves
  1055. to the archive, it becomes read only.  
  1056. A page can be moved from the archive to the magnetic disk if its parent
  1057. page resides on magnetic disk.  In this case, the 
  1058. archive page previously inhabited by this page becomes unusable.
  1059. The utility of this reverse migration seems limited, so we will not consider
  1060. it further.
  1061. .pp
  1062. We turn now to several page movement policies for migrating pages from
  1063. magnetic disk to the archive and use the parameters indicated in Table
  1064. 4 in the discussion to follow.
  1065. .(z
  1066. .hl
  1067. .(c
  1068. .TS
  1069. c c
  1070. l l.
  1071. F    number of magnetic disk blocks usable for the index
  1072. U    update frequency of the relation being indexed
  1073. L    record size in the index being constructed
  1074. B    block size of magnetic disk pages
  1075. .TE
  1076. .)c
  1077. .sp
  1078. .ce
  1079. Parameters Controlling Page Movement
  1080. .ce
  1081. Table 4
  1082. .hl
  1083. .)z
  1084. The simplist policy would be to construct a system demon to
  1085. ``vacuum'' the index by moving the leaf page to the archive that has
  1086. the smallest value for Tmax, the left-hand end of its interval.
  1087. This vacuuming would occur whenever the R-tree structure reached 
  1088. a threshold near its maximum size of F disk pages.  A second
  1089. policy would be to choose a worthy page to archive based both on
  1090. its value of Tmax and on percentage fullness of the page.
  1091. In either case, insertions 
  1092. would be made into
  1093. the R-tree index at the lower left-hand part of the index while
  1094. the demon would be archiving pages in the lower right hand part of the
  1095. index.  Whenever an intermediate R-tree node had descendents all on
  1096. the archive, it could in turn be archived by the demon.
  1097. .pp
  1098. For example,
  1099. if B is 8192 bytes, L is 50 bytes and 
  1100. there is a five year archive of updates at a frequency, U of 
  1101. 1 update per second, then 
  1102. 1.4 x 10**6 index blocks will be required resulting in a four
  1103. level R-tree.  F of these blocks will
  1104. reside on magnetic disk and the remainder will be on the
  1105. archive.  Any insertion or search will require at least 4
  1106. accesses to one or the other storage medium.
  1107. .pp
  1108. A third movement policy with somewhat different 
  1109. performance characteristics would
  1110. be to perform ``batch movement''.  In this case one would
  1111. build a magnetic disk R-tree until its size was F blocks.  Then, one
  1112. would copy the all pages of the R-tree except the root to 
  1113. the archive and allocate a special
  1114. ``top node'' on magnetic disk for this root 
  1115. node.  Then, one would proceed to fill up a second
  1116. complete R-tree of F-1 pages.  
  1117. While the second R-tree was being built, both this new R-tree and the
  1118. one on the archive would be searched during any retrieval request.
  1119. All inserts would, of course, be directed to the magnetic disk R-tree.
  1120. When this second R-tree was full, it would be copied to the archive as before
  1121. and its root node added to the existing top node.  The combination
  1122. might cause the top node to overflow, and a conventional R-tree split would
  1123. be accomplished.  Consequently, the top node would become a conventional R-tree
  1124. of three nodes.  The filling process would start again on a 3rd R-tree
  1125. of F-3 nodes.  When this was full, it would be archived and its root
  1126. added to the lower left hand page of the 3 node R-tree.  
  1127. .pp
  1128. Over time, 
  1129. there would continue to be two R-trees. The first would be
  1130. completely on magnetic disk
  1131. and periodically archived.  As long as the height of this R-tree
  1132. at the time it is archived is a constant, H, then the second R-tree
  1133. of height, H1, will have the bottom H-1 levels 
  1134. on the archive.  
  1135. Moreover, insertions into the magnetic disk portion of this R-tree
  1136. are always on the left-most page.  Hence, the pages along the left-side
  1137. of the tree are the only ones which will be modified; other pages
  1138. can be archived if they point entirely to
  1139. pages on the archive.  Hence, some subcollection of the 
  1140. pages on the top H1-H+1 levels remain on the
  1141. magnetic disk.  Insertions go always to the first R-tree while
  1142. searches go to both R-trees.  Of course, there are no deletions
  1143. to be concerned with.
  1144. .pp
  1145. Again if B is 8192 bytes, L is 50 bytes and F is 6000 blocks, then H will
  1146. be 3 and each insert will require 3 magnetic disk 
  1147. accesses.  Moreover, at 1 update per second, a five year archive 
  1148. will require a four
  1149. level R-tree whose bottom two levels will be on the archive and
  1150. a subcollection of the top 2 levels of 100-161 blocks 
  1151. will be on magnetic disk.  Hence,
  1152. searches will require descending two R-trees with a total depth of
  1153. 7 levels and will be about 40 percent slower than 
  1154. either of the single R-tree structures proposed.  On the other hand,
  1155. the very common operation of insertions will be
  1156. approximately 25 percent faster.
  1157. .sh 1  "PERFORMANCE COMPARISON"
  1158. .sh 2  "Assumptions"
  1159. .pp
  1160. In order to compare our storage system with a conventional one based
  1161. on write-ahead logging (WAL), we make the
  1162. following assumptions.
  1163.  
  1164. 1) Portions of the buffer pool may reside in non-volatile main memory
  1165.  
  1166. 2) CPU instructions are not a critical resource, and thereby only
  1167. I/O operations are counted.
  1168.  
  1169. The second assumption requires some explanation.  Current CPU technology
  1170. is driving down the cost of a MIP at a rate of a factor of two every couple
  1171. of years.  Hence, current low-end workstations have a few MIPs of processing
  1172. power.  On the other hand, disk technology is getting denser and cheaper.
  1173. However, disks are not getting faster at a significant rate.  Hence, one 
  1174. can still only expect to read about 30 blocks per second off of a standard disk
  1175. drive.  Current implementations of data base systems require several
  1176. thousand instructions to fetch a page from the disk followed by 
  1177. 1000-3000 instructions per data record examined on that page.  As a simple
  1178. figure of merit, assume 
  1179. 30000 instructions
  1180. are required to process a disk block.  Hence, a
  1181. 1 MIP CPU will approximately balance a single disk.  Currently, workstations
  1182. with 3-5 MIPs are available but are unlikely to be configured with 3-5
  1183. disks.  Moreover, future workstations (such as SPUR and FIREFLY) 
  1184. will have 10-30 MIPs.  Clearly, they will not have 10-30 disks unless
  1185. disk systems shift to large numbers of SCSI oriented single platter
  1186. disks and away from current SMD disks.
  1187. .pp
  1188. Put differently, a SUN 3/280 costs about $5000 per MIP, while an SMD 
  1189. disk and controller costs about $12,000.  Hence, the CPU cost to support
  1190. a disk is much smaller than the cost of the disk, and the major cost of data
  1191. base hardware can be expected to be in the disk system.  As such, if an
  1192. installation is found to be CPU bound, then additional CPU resources can be
  1193. cheaply added until the system becomes balanced.  
  1194. .pp
  1195. We
  1196. analyze three possible situations:
  1197. .(l
  1198. large-SM:    an ample amount of stable main memory is available
  1199. small-SM:    a modest amount of stable main memory is available
  1200. no-SM:    no stable main memory is availble
  1201. .)l
  1202. In the first case we assume 
  1203. that enough stable main memory is available for POSTGRES and a WAL system
  1204. to use so that
  1205. neither
  1206. system is required to 
  1207. .b force 
  1208. disk pages to secondary storage at the time that they are updated.  Hence, each
  1209. system will execute a certain number of 
  1210. I/O operations that can be buffered in stable memory and written out to
  1211. disk at some convenient time.  We count the
  1212. number of such
  1213. .b non-forced
  1214. I/O operations that each system will execute, assuming all
  1215. writes cost the same amount.  
  1216. For both systems we assume that records do not cross page boundaries,
  1217. so each update results in a single page write.  Moreover, we assume that
  1218. each POSTGRES delta record can be put 
  1219. on the same page as its anchor point.
  1220. Next, we assume that transactions are a single record insertion,
  1221. update, deletion or an aborted update.  Moreover, we assume 
  1222. there are two secondary indexes
  1223. on the relation affected and that updates fail to alter either key field.
  1224. Lastly, we assume that a write ahead log will require 3 log
  1225. records (begin transaction, the data modification, and end
  1226. transaction), with a total length of 400 bytes.  
  1227. Moreover, secondary index operations are not logged
  1228. and thereby the log records for 10 transactions will fit on a
  1229. conventional 4K log page.
  1230. .pp
  1231. In the second situation we assume
  1232. that a modest amount of stable main memory is available.  We assume
  1233. that the quantity is sufficient to hold only
  1234. the tail of the POSTGRES log and the tail of the TIME relation.
  1235. In a WAL system, we assume that 
  1236. stable memory can buffer a conventional log turning each log
  1237. write into one that need not be synchronously forced out to
  1238. disk.  
  1239. This situation (small-SM) should be contrasted with the
  1240. third case where no stable memory at all is available (no-SM).
  1241. In this latter cases, some writes must be forced to disk
  1242. by both types of storage systems.
  1243. .pp
  1244. In the results to follow we ignore the cost that either kind of system 
  1245. would incur to mirror the data for high availability.
  1246. Moreover, we are also ignoring the WAL 
  1247. cost associated with checkpoints.
  1248. In addition, we assume that a WAL system never requires 
  1249. a disk read
  1250. to access the appropriate un-do log record.
  1251. We are also ignoring the cost of vacuuming the disk in the POSTGRES
  1252. architecture.  
  1253. .sh 2  "Performance Results"
  1254. .pp
  1255. Table 5 indicates the number of I/O operations each 
  1256. of the
  1257. four types of transactions must execute
  1258. for the assumed large-SM configuration.
  1259. Since there is ample stable main memory, neither system must force
  1260. any data pages to disk and only non-forced I/Os must be done.
  1261. An insert requires that a data record and two index records be written
  1262. by either system. Moreover, 1/10th of a log page will be filled by the
  1263. conventional system, so every 10 transactions there will be another
  1264. log page which must be eventually written to disk.  In POSTGRES 
  1265. the insertions to the LOG relation and the TIME relation generate
  1266. an I/O every 65536 and 2048 transactions respectively, and we 
  1267. have ignored this 
  1268. small number in Table 5.  Consequently, 
  1269. one requires 
  1270. 3 non-forced I/Os in POSTGRES and 3.1 in a conventional system.  The
  1271. next two columns in Table 1 can be
  1272. similarly computed.
  1273. The last column summarizes the I/Os for an aborted transaction.  In POSTGRES
  1274. the updated page need not be rewritten to disk.  Hence, no I/Os are strictly
  1275. necessary; however, in all liklihood, this 
  1276. optimization will not be implemented.
  1277. A WAL system will update the data and construct a log record.  Then the log
  1278. record must be read and the data page returned to its original value.
  1279. Again, a very clever system could avoid writing the page out to disk, since
  1280. it is identical to the disk copy.  Hence, for both systems we indicate
  1281. both the optimized number of writes and the non-optimized number.
  1282. Notice in Table 5 that POSTGRES is marginally better than a WAL system
  1283. except for deletes where it is dramatically better because it does not
  1284. delete the 2 index records.  We now turn to cases where POSTGRES is less
  1285. attractive.
  1286. .(z
  1287. .hl
  1288. .(c
  1289. .TS
  1290. c c c c c
  1291. l l l l l.
  1292.     Insert    Update    Delete    Abort
  1293.  
  1294. WAL-force    0    0    0    0
  1295. WAL-no-force    3.1    1.1    3.1    0.1 or 1.1
  1296.  
  1297.  
  1298. POSTGRES-force    0    0    0    0
  1299. POSTGRES-non-force    3    1    1    0 or 1
  1300. .TE
  1301. .)c
  1302. .sp
  1303. .ce
  1304. I/O Counts for the Primitive Operations
  1305. .ce 
  1306. large-SM Configuration
  1307. .ce
  1308. Table 5
  1309. .hl
  1310. .)z
  1311. .pp
  1312. Table 6 repeats the I/O counts for the small-SM configuration.  The WAL
  1313. configuration performs exactly as in Table 5 while the the POSTGRES 
  1314. data pages must now be forced to disk since insufficient stable main
  1315. memory is assumed to hold them.
  1316. Notice that POSTGRES is still better in the total number of I/O operations;
  1317. however the requirement to do them synchronously will be a major disadvantage.
  1318. .(z
  1319. .hl
  1320. .(c
  1321. .TS
  1322. c c c c c
  1323. l l l l l.
  1324.     Insert    Update    Delete    Abort
  1325.  
  1326. WAL-force    0    0    0    0
  1327. WAL-no-force    3.1    1.1    3.1    0.1 or 1.1
  1328.  
  1329. POSTGRES-force    3    1    1    0 or 1
  1330. POSTGRES-non-force    0    0    0    0
  1331. .TE
  1332. .)c
  1333. .sp
  1334. .ce
  1335. I/O Counts for the Primitive Operations
  1336. .ce 
  1337. small-SM Configuration
  1338. .ce
  1339. Table 6
  1340. .hl
  1341. .)z
  1342. .pp
  1343. Table 7 then indicates the I/O counts under the condition that NO
  1344. stable main memory is available.  Here the log record for a 
  1345. conventional WAL system must be forced to disk at commit time.
  1346. The other writes can remain in the buffer pool and be written at
  1347. a later time.  In POSTGRES the 
  1348. LOG bit must be forced out to disk along with the insert to the TIME
  1349. relation.  Moreover, the data pages must be forced as in Table 6.
  1350. In this case POSTGRES is marginally poorer in the total number of
  1351. operations; and again the synchronous nature of these updates will
  1352. be a significant disadvantage.
  1353. .(z
  1354. .hl
  1355. .(c
  1356. .TS
  1357. c c c c c
  1358. l l l l l.
  1359.     Insert    Update    Delete    Abort
  1360.  
  1361. WAL-force    1    1    1    1
  1362. WAL-no-force    3    1    3    0 or 1
  1363.  
  1364. POSTGRES-force    5    3    3    1
  1365. POSTGRES-non-force    0    0    0    0 or 1
  1366. .TE
  1367. .)c
  1368. .sp
  1369. .ce
  1370. I/O Counts for the Primitive Operations
  1371. .ce 
  1372. no-SM Configuration
  1373. .ce
  1374. Table 7
  1375. .hl
  1376. .)z
  1377. .pp
  1378. In summary,
  1379. the POSTGRES solution is preferred in the large-SM
  1380. configuration since all operations require less I/Os.  In Table 6
  1381. the total number of I/Os is less for POSTGRES; however, 
  1382. synchronous I/O is
  1383. required.  
  1384. Table 7 shows a situation where POSTGRES is typically more expensive.
  1385. However, group commits [DEWI84] could be used to effectively convert the
  1386. results for either type of system into
  1387. the ones in Table 6.
  1388. Consequently, POSTGRES should be thought of as fairly competitive with
  1389. current storage architectures.  Moreover, it has a considerable advantage
  1390. over WAL systems in that
  1391. recovery time will be instantaneous while 
  1392. requiring a substantial amount of time in a WAL architecture.
  1393. .sh 1  "CONCLUSIONS"
  1394. .pp
  1395. This paper has described the storage manager that is being constructed for
  1396. POSTGRES.  The main points guiding the design of the system were:
  1397.  
  1398. 1) instantaneous recovery from crashes
  1399.  
  1400. 2) ability to keep archival records on an archival medium
  1401.  
  1402. 3) housekeeping chores should be done asynchronously
  1403.  
  1404. 4) concurrency control based on conventional locking
  1405.  
  1406. The first point should be contrasted with the standard write-ahead log (WAL)
  1407. storage managers in widespread use today.  
  1408. .pp
  1409. In engineering application
  1410. one often requires the past history of the data base.  Moreover, even 
  1411. in business applications this feature is sometimes needed, and the now
  1412. famous TP1 benchmark assumes that the application will maintain an
  1413. archive.  It makes more sense for the data manager to do this
  1414. task internally for applications that require the service.  
  1415. .pp
  1416. The third
  1417. design point has been motivated by the desire to run multiple
  1418. concurrent processes if there happen to be extra processors.  Hence
  1419. storage management functions can occur in parallel on multiple processors.
  1420. Alternatively, some functions can be saved for idle time on a single processor.
  1421. Lastly, it allows POSTGRES code to be a collection of asynchronous
  1422. processes and not a single large monolithic body of code.
  1423. .pp
  1424. The final design point reflects our intuitive belief, confirmed
  1425. by simulations, that standard locking is the most desirable
  1426. concurrency control strategy.  Moreover, it should be noted that 
  1427. read-only transactions can be optionally coded to run as of
  1428. some point in the recent past.  Since historical commands 
  1429. set no locks, then read-only transactions will never
  1430. interfere with transactions performing updates or be required to
  1431. wait.  Consequently, the level of contention in
  1432. a POSTGRES data base may be a great deal lower than that found in
  1433. conventional storage managers.
  1434. .pp
  1435. The design of the POSTGRES storage manager has been sketched and a brief
  1436. analysis of its expected performance relative to a conventional
  1437. one has been performed.  If the analysis is confirmed in practice, then POSTGRES
  1438. will give similar performance compared to other storage managers
  1439. while providing the extra service of historical access to the
  1440. data base.  This should prove attractive in some environments.
  1441. .pp
  1442. At the moment, the magnetic disk storage manager is operational,
  1443. and work is proceeding on the vacuum cleaner and the layout
  1444. of the archive.  POSTGRES is designed to support extendible access methods, and
  1445. we have implemented the B-tree code and will provide R-trees in the
  1446. near future.  Additional access methods can be constructed by 
  1447. other parties to suit their special needs.  When the remaining pieces
  1448. of the storage manager are complete, we plan a performance ``bakeoff''
  1449. both against conventional storage managers as well as against other
  1450. storage managers (such as [CARE86, COPE84]) with interesting properties.
  1451.  
  1452. \fBREFERENCES\fP
  1453. .nr ii 10m
  1454. .ip [AGRA85]
  1455. Agrawal, R. et. al., ``Models for Studying Concurrency Control Performance
  1456. Alternatives and Implications,'' Proc. 1985 ACM-SIGMOD Conference on Management
  1457. of Data, Austin, Tx., May 1985.
  1458. .ip [ASTR76]
  1459. Astrahan, M. et. al., ``System R: A Relational Approach to Data,'' ACM-TODS,
  1460. June 1976.
  1461. .ip [BART81]
  1462. Bartlett, J., ``A Non-STOP Kernel,'' Proc. Eighth Symposium on 
  1463. Operating System
  1464. Principles,'' Pacific Grove, Ca., Dec. 1981.
  1465. .ip [BERN80]
  1466. Bernstein, P. at. al., ``Concurrency Control in a System for Distributed
  1467. Databases (SDD-1),'' ACM-TODS, March 1980.
  1468. .ip [BHID87]
  1469. Bhide, A., ``Query Processing in Shared Memory Multiprocessor Systems,'' (in
  1470. preparation).
  1471. .ip [CARE86]
  1472. Carey, M. et. al., "Object and File Management in the EXODUS Database System,''
  1473. Proc. 1986 VLDB Conference, Kyoto, Japan, August 1986.
  1474. .ip [COPE84]
  1475. Copeland, G. and D. Maier, ``Making Smalltalk a Database System,''
  1476. Proc. 1984 ACM-SIGMOD Conference on Management of Data, Boston, Mass.
  1477. June 1984.
  1478. .ip [DEC86]
  1479. Digital Equipment Corp., ``VAX/VMS V4.0 Reference Manual,'' Digital Equipment
  1480. Corp., Maynard, Mass., June 1986.
  1481. .ip [DEWI84]
  1482. Dewitt, D. et. al., ``Implementation Techniques for Main Memory Database
  1483. Systems,'' Proc. 1984 ACM-SIGMOD Conference on Management of Data, Boston,
  1484. Mass., June 1984.
  1485. .ip [GRAY78]
  1486. Gray, J., ``Notes on Data Base Operating Systems,'' IBM Research, 
  1487. San Jose, Ca., RJ1879, June 1978.
  1488. .ip [GUTM84]
  1489. Gutman, A., ``R-trees: A Dynamic Index Structure for Spatial Searching,''
  1490. Proc. 1984 ACM-SIGMOD Conference on Management of Data, Boston, Mass.
  1491. June 1984.
  1492. .ip [HILL86]
  1493. Hill, M., et al. ``Design Decisions in SPUR,''
  1494. Computer Magazine, vol.19, no.11, November 1986.
  1495. .ip [ROUS85]
  1496. Roussoupoulis, N. and Leifker, D., ``Direct Spatial Search on Pictorial
  1497. Databases Using Packed R-trees,'' Proc. 1985 ACM-SIGMOD Conference
  1498. on Management of Data, Austin, Tx., May 1985.
  1499. .ip [SEQU85]
  1500. Sequent Computer Co., ``The SEQUENT Balance Reference Manual,'' Sequent
  1501. Computers, Portland, Ore., 1985.
  1502. .ip [SEVR76]
  1503. Severence, D., and Lohman, G., ``Differential Files: Their Application
  1504. to the Maintenance of large Databases,'' ACM-TODS, June 1976.
  1505. .ip [STON76]
  1506. Stonebraker, M., et. al. ``The Design and Implementation of INGRES,''
  1507. ACM-TODS, September 1976.
  1508. .ip [STON86]
  1509. Stonebraker, M. and Rowe, L., ``The Design of POSTGRES,'' Proc. 1986ACM-SIGMOD
  1510. Conference on Management of Data, Washington, D.C., May 1986.
  1511. .ip [STON86a]
  1512. Stonebraker, M., ``Inclusion of New Types in Relational Data Base Systems,''
  1513. Proc. Second International Conference on Data Base Engineering, Los Angeles,
  1514. Ca., Feb. 1986.
  1515. .ip [VITT85]
  1516. Vitter, J., ``An Efficient I/O Interface for Optical Disks,'' ACM-TODS,
  1517. June 1985.
  1518.  
  1519.