Annotation of 42BSD/ingres/doc/other/maintain.nr, revision 1.1

1.1     ! root        1: .ds HE 'DATA BASE'INGRES'Page %'
        !             2: .so nmacs
        !             3: .hx
        !             4: .rs
        !             5: .sp 8
        !             6: .ce
        !             7: CREATING AND MAINTAINING A DATABASE USING INGRES
        !             8: .sp 15
        !             9: .ce
        !            10: by
        !            11: .ce
        !            12: Robert Epstein
        !            13: .sp 18
        !            14: .ce 2
        !            15: Memorandum No. ERL - M77-71
        !            16: December 16, 1977
        !            17: .sp 3
        !            18: .ce 4
        !            19: Electronics Research Laboratory
        !            20: College of Engineering
        !            21: University of California, Berkeley
        !            22: 94720
        !            23: .bp 1
        !            24: .ce
        !            25: .bl + 5
        !            26: CREATING AND MAINTAINING A DATABASE USING INGRES
        !            27: .sp 3
        !            28: 1.   INTRODUCTION
        !            29: .sp
        !            30: In this paper we describe how to create,
        !            31: structure and maintain relations
        !            32: in INGRES.
        !            33: It is assumed that the reader
        !            34: is familiar with INGRES
        !            35: and understands QUEL, the INGRES
        !            36: query language.
        !            37: It is strongly suggested that the
        !            38: document "A Tutorial on INGRES"
        !            39: (ERL M77/25) be read first.
        !            40: .sp 1
        !            41: This paper is divided into six sections
        !            42: .in +5
        !            43: .sp 1
        !            44: 1.  Introduction
        !            45: .sp 1
        !            46: 2.  Creating a Relation
        !            47: .sp 1
        !            48: 3.  Using Copy
        !            49: .sp 1
        !            50: 4.  Storage Structures
        !            51: .sp 1
        !            52: 5.  Secondary Indices
        !            53: .sp 1
        !            54: 6.  Recovery and Data Update
        !            55: .in -5
        !            56: .sp 1
        !            57: To create a new data base you must be a valid
        !            58: INGRES user and have "create data base"
        !            59: permission.
        !            60: These permissions are granted by the
        !            61: "ingres" superuser.
        !            62: If you pass those two requirements you can create
        !            63: a data base using the command to the
        !            64: Unix shell:
        !            65: .sp 1
        !            66: % creatdb mydata
        !            67: .sp 1
        !            68: where "mydata" is the name of the data base.
        !            69: You become the "data base administrator" (DBA) for
        !            70: mydata.
        !            71: As the DBA you have certain special
        !            72: powers.
        !            73: 
        !            74: .in +4
        !            75: .ti -5
        !            76: 1.  Any relation created by you can be accessed
        !            77: by anyone else using "mydata".
        !            78: If any other user creates a relation it is
        !            79: strictly private and cannot
        !            80: be accessed by the DBA or any other user.
        !            81: 
        !            82: .ti -5
        !            83: 2.  You can use the "-u" flag in ingres
        !            84: and printr. 
        !            85: This enables you to use ingres on "mydata"
        !            86: with someone else's id.
        !            87: Refer to the INGRES reference
        !            88: manual under sections
        !            89: ingres(unix) and users(files)
        !            90: for details.
        !            91: 
        !            92: .ti -5
        !            93: 3.  You can run sysmod, restore and purge
        !            94: on "mydata".
        !            95: 
        !            96: .ti -5
        !            97: 4.  The data base by default is created to
        !            98: allow for multiple concurrent users.
        !            99: If only one user will ever use the
        !           100: data base at a time,
        !           101: the data base administrator can
        !           102: turn off the concurrency control.
        !           103: Refer to creatdb(unix) in the INGRES
        !           104: reference manual.
        !           105: .in -4
        !           106: .sp 1
        !           107: Once a data base has been created you should
        !           108: immediately run
        !           109: .sp 1
        !           110: % sysmod mydata
        !           111: .sp 1
        !           112: This program will convert
        !           113: the system relations to their
        !           114: "best" structure for use in INGRES.
        !           115: Sysmod will be explained further in
        !           116: section 4.
        !           117: .sp 1
        !           118: As a DBA or as a user you can create and
        !           119: structure new relations in any data
        !           120: base to which you have access.
        !           121: The remainder of this paper describes how this is done.
        !           122: .bp
        !           123: 2.   CREATING NEW RELATIONS IN INGRES
        !           124: .sp
        !           125: There are two ways to create new relations in INGRES.
        !           126: .sp 1
        !           127: .ti +5
        !           128: create
        !           129: .br
        !           130: .ti +5
        !           131: retrieve into
        !           132: .sp 1
        !           133: "Retrieve into" is used to form a new relation from one or
        !           134: more existing relations.
        !           135: "Create" is used to create
        !           136: a new relation with no tuples in it.
        !           137: .sp 1
        !           138: example 1:
        !           139: .sp 1
        !           140: .ti +5
        !           141: range of p is parts
        !           142: .ti +5
        !           143: range of s is supply
        !           144: .ti +5
        !           145: retrieve into newsupply(
        !           146: .ti +19
        !           147: number = s.snum,
        !           148: .ti +19
        !           149: p.pname,
        !           150: .ti +19
        !           151: s.shipdate)
        !           152: .ti +5
        !           153: where s.pnum = p.pnum
        !           154: .sp 1
        !           155: example 2:
        !           156: .sp 1
        !           157: .ti +5
        !           158: create newsupply(
        !           159: .ti +12
        !           160: number = i2,
        !           161: .ti +12
        !           162: pname = c20,
        !           163: .ti +12
        !           164: shipdate = c8)
        !           165: .sp 1
        !           166: In example 1 INGRES creates a new relation called
        !           167: "newsupply", computing what the format
        !           168: of each domain should be.
        !           169: The query is then run and newsupply is
        !           170: modified to "cheapsort".
        !           171: (This will be covered in more detail in section 4.)
        !           172: .sp 1
        !           173: In example 2 "newsupply"
        !           174: is created and the name and
        !           175: format for each domain is given.
        !           176: The format types which are
        !           177: allowed are:
        !           178: .sp 1
        !           179: .in +5
        !           180: .nf
        !           181: i1             1  byte integer
        !           182: i2             2   "      "
        !           183: i4             4   "      "
        !           184: f4             4  byte floating point number
        !           185: f8             8   "      "       "     "
        !           186: c1,c2,..,c255  1,2,..,255 byte character
        !           187: .in -5
        !           188: .fi
        !           189: .sp 1
        !           190: In example 2, the width of an individual
        !           191: tuple is 30 bytes
        !           192: (2 + 20 + 8), and the
        !           193: relation has three domains.
        !           194: Beware that INGRES
        !           195: has limits.
        !           196: A relation cannot have more
        !           197: than 49 domains and the tuple width
        !           198: cannot exceed 498 bytes.
        !           199: .sp 1
        !           200: UNIX allocates space on a disk
        !           201: in units of 512 byte pages.
        !           202: INGRES gets a performance advantage
        !           203: by doing I/O in one block units.
        !           204: Therefore relations are divided into 512 byte pages.
        !           205: INGRES never splits a tuple
        !           206: between two pages.
        !           207: Thus some space can be wasted.
        !           208: There is an overhead of 12 bytes per page plus
        !           209: 2 bytes for every tuple on the page.
        !           210: The formulas are:
        !           211: .sp 1
        !           212: .ti +5
        !           213: number tuples per page = 500/(tuple width + 2)
        !           214: .sp 1
        !           215: .ti +5
        !           216: wasted space = 500 - number of tuples per page
        !           217: .ti +5
        !           218: *(tuple width +2)
        !           219: .sp 1
        !           220: For our example there are
        !           221: .sp 1
        !           222: .ti +5
        !           223: 22 = 500/(20 + 2)
        !           224: .sp 1
        !           225: .ti +5
        !           226: 16 = 500 - 22 * (20 + 2)
        !           227: .sp 1
        !           228: 22 tuples per page and 16 bytes
        !           229: wasted per page.
        !           230: These computations are valid
        !           231: only for uncompressed relations.
        !           232: We will return to this subject
        !           233: in section 4 when we discuss compression.
        !           234: .sp 1
        !           235: If you forget a domain name or
        !           236: format, use the "help" command.
        !           237: For example if you gave the INGRES
        !           238: command:
        !           239: .sp 1
        !           240: .ti +5
        !           241: help newsupply
        !           242: .sp 1
        !           243: the following would be printed:
        !           244: .nf
        !           245: 
        !           246: Relation:              newsupply
        !           247: Owner:                 bob
        !           248: Tuple width:           30
        !           249: Saved until:           Thu Nov 10 16:17:06 1977
        !           250: Number of tuples:      0
        !           251: Storage structure:     paged heap
        !           252: Relation type:         user relation
        !           253: 
        !           254:  attribute name    type  length  keyno.
        !           255: 
        !           256:  number            i       2
        !           257:  pname             c      20
        !           258:  shipdate          c       8
        !           259: 
        !           260: .fi
        !           261: Notice that every relation has an expiration
        !           262: date.
        !           263: This is set to be one week
        !           264: from the time when it was
        !           265: created.
        !           266: The "save" command
        !           267: can be used to save the relation longer.
        !           268: See "save(quel)" and "purge(unix)" in the 
        !           269: INGRES reference manual.
        !           270: 
        !           271: .bp
        !           272: 3.   COPYING DATA TO AND FROM INGRES
        !           273: .sp
        !           274: Once a relation is created, there are two mechanisms for
        !           275: inserting new data:
        !           276: .sp
        !           277: .in +5
        !           278: append command
        !           279: .br
        !           280: copy command
        !           281: .in -5
        !           282: .sp
        !           283: Append is used to insert tuples one at a time,
        !           284: or for filling one relation from other relations.
        !           285: .sp
        !           286: Copy is used for copying data from a UNIX file into
        !           287: a relation. 
        !           288: It is used for copying data from another program, or for copying
        !           289: data from another system.  
        !           290: It is also the most convenient way to copy any data
        !           291: larger than a few tuples.
        !           292: .sp
        !           293: Let's begin by creating a simple relation
        !           294: and loading data into it.
        !           295: .sp
        !           296: Example:
        !           297: .sp
        !           298: .ti +5
        !           299: .nf
        !           300: create donation (name = c10, amount = f4, ext = i2)
        !           301: .sp
        !           302: .fi
        !           303: Now suppose we have two people to enter.  
        !           304: The simplest procedure is probably
        !           305: to run the two queries in INGRES using
        !           306: the append command.
        !           307: .sp
        !           308: .ti 5
        !           309: .nf
        !           310: append to donation (name="frank",amount = 5,ext = 204)
        !           311: .sp 1
        !           312: .ti 5
        !           313: append to donation (name="harry",ext = 209,amount = 4.50)
        !           314: .fi
        !           315: .sp
        !           316: Note that the order in which the domains are given
        !           317: does not matter.
        !           318: INGRES matches by recognizing attribute names and
        !           319: does not care in what order attributes
        !           320: are listed.
        !           321: Here is what the relation "donation" looks like now:
        !           322: .nf
        !           323: 
        !           324: donation relation
        !           325: 
        !           326: |name      |amount    |ext   |
        !           327: |----------------------------|
        !           328: |frank     |5.000     |204   |
        !           329: |harry     |4.500     |209   |
        !           330: |----------------------------|
        !           331: .fi
        !           332: .sp
        !           333: We now have two people entered into
        !           334: the donation relation.
        !           335: Suppose we had fifty more to enter.
        !           336: Using the append command is far too tedious
        !           337: since so much typing is involved for each tuple.
        !           338: The copy command will better suit our purposes.
        !           339: .sp
        !           340: Copy can take data from a regular
        !           341: Unix file in a variety of formats and
        !           342: append it to a relation.
        !           343: To use the copy command first create
        !           344: a Unix file (typically using "ed") containing
        !           345: the data.
        !           346: .sp
        !           347: For example, let's put five new names in a file
        !           348: using the editor.
        !           349: .sp
        !           350: .nf
        !           351: .tr Z.
        !           352: % ed
        !           353: a
        !           354: bill,3.50,302
        !           355: sam,10.00,410
        !           356: susan,,100
        !           357: sally,.5,305
        !           358: george,4.00,302
        !           359: Z
        !           360: w newdom
        !           361: 68
        !           362: q
        !           363: %
        !           364: .tr ZZ
        !           365: .sp 
        !           366: .fi
        !           367: The format of the above file is a
        !           368: name followed by a comma, followed 
        !           369: by the amount, then a comma, then the extension,
        !           370: and finally a newline.
        !           371: Null entries, for example the amount
        !           372: for susan, are perfectly
        !           373: legal and default to zero
        !           374: for numerical domains and
        !           375: blanks for character domains.
        !           376: .sp
        !           377: To use copy we enter INGRES and give the copy command.
        !           378: .sp
        !           379: .in +5
        !           380: .nf
        !           381: copy donation (name = c0, amount = c0, ext = c0)
        !           382:        from "/mnt/bob/newdom"
        !           383: .fi
        !           384: .sp
        !           385: .in -5
        !           386: Here is how the copy command works:
        !           387: .sp
        !           388: .ti +5
        !           389: copy relname (list of what to copy) from "full pathname"
        !           390: .sp
        !           391: In the case above we wrote:
        !           392: .sp
        !           393: .ti +5
        !           394: copy donation (. . .) from "/mnt/bob/newdom"
        !           395: .sp
        !           396: Although amount and ext are stored in the relation
        !           397: as f4 (floating point) and i2 (integer), in the
        !           398: Unix file they were entered as characters.
        !           399: In specifying the format of the domain,
        !           400: copy accepts:
        !           401: .sp
        !           402: .ti +5
        !           403: domain = format
        !           404: .sp
        !           405: where domain is the domain name and
        !           406: the format in the UNIX file is one of
        !           407: .sp
        !           408: .in +5
        !           409: .nf
        !           410: i1, i2, i4         (true binary integer of size 1, 2, or 4)
        !           411: .br
        !           412: f4, f8             (true binary float point of size 4 or 8)
        !           413: .br
        !           414: c1, c2, c3,...c255 (a fixed length character string)
        !           415: .br
        !           416: c0                 (a variable length character string de-
        !           417:                    limited by a comma, tab or new line)
        !           418: .sp
        !           419: .in -5
        !           420: .fi
        !           421: In the example we use
        !           422: .sp
        !           423: .ti +5
        !           424: name = c0, amount = c0, extension = c0
        !           425: .sp
        !           426: This means that each of the domains
        !           427: was stored in the Unix file as
        !           428: variable length character
        !           429: strings.
        !           430: Copy takes the first comma,
        !           431: tab, or new line character
        !           432: as the end of the string.
        !           433: This by far is the most
        !           434: common use of copy
        !           435: when the data is being entered
        !           436: into a relation
        !           437: for the first time.
        !           438: .sp
        !           439: Copy can also be used to copy data from a relation
        !           440: into a Unix file.
        !           441: For example:
        !           442: .sp
        !           443: .in +5
        !           444: .nf
        !           445: copy donation (name = c10, amount = c10, ext = c5)
        !           446:         into "/mnt/bob/data"
        !           447: .fi
        !           448: .in -5
        !           449: .sp
        !           450: This will cause the following to happen:
        !           451: .sp 1
        !           452: .in +4
        !           453: .ti -5
        !           454: 1.  If the file /mnt/bob/data already exists it will
        !           455: be destroyed.
        !           456: .ti -5
        !           457: .sp 1
        !           458: 2.  The file is created in mode 600 (read/write by you only)
        !           459: .sp 1
        !           460: .ti -5
        !           461: 3.  Name will be copied as a 10 character field,
        !           462: immediately followed by amount,
        !           463: immediately followed by ext.
        !           464: Amount will be converted to a character
        !           465: field 10 characters wide.
        !           466: Ext will be converted to a character
        !           467: field 5 characters wide.
        !           468: .in -4
        !           469: .sp 1
        !           470: The file "/mnt/bob/data" would be a stream of characters
        !           471: looking like this:
        !           472: 
        !           473: .tr Z 
        !           474: .nf
        !           475: frankZZZZZZZZZZ5.000ZZ204harryZZZZZZZZZZ4.500ZZ209bill
        !           476: ZZZZZZZZZZZ3.500ZZ302samZZZZZZZZZZZ10.000ZZ410susanZZZ
        !           477: ZZZZZZZ0.000ZZ100sallyZZZZZZZZZZ0.500ZZ305georgeZZZZZZ
        !           478: ZZZ4.000ZZ302
        !           479: .fi
        !           480: .tr ZZ
        !           481: 
        !           482: .sp
        !           483: The output was broken into four lines to
        !           484: make it fit on this page.
        !           485: In actuality the file
        !           486: is a single line.
        !           487: Another example:
        !           488: .sp
        !           489: .in +5
        !           490: .nf
        !           491: copy (name = c0, colon = d1, ext = c0, comma = d1
        !           492:        amt = c0, nl = d1) into "/mnt/bob/data"
        !           493: .fi
        !           494: .in -5
        !           495: .sp
        !           496: In this example "c0" is interpreted to mean "use
        !           497: the appropriate character format".
        !           498: For character domains it is the
        !           499: width of the domain.
        !           500: Numeric domains are converted to characters
        !           501: according to the INGRES defaults
        !           502: (see ingres(unix)).
        !           503: .sp
        !           504: The statements:
        !           505: .sp
        !           506: .in +5
        !           507: colon = d1
        !           508: .br
        !           509: comma = d1
        !           510: .br
        !           511: nl = d1
        !           512: .in -5
        !           513: .sp
        !           514: are used to insert one colon,
        !           515: comma, and newline into the file.
        !           516: The format "d1" is interpreted to mean
        !           517: one dummy character.
        !           518: When copying into a Unix file,
        !           519: a selected set of characters can be inserted into
        !           520: the file using this
        !           521: "dummy domain" specification.
        !           522: Here is what the file "/mnt/bob/data" would look like:
        !           523: 
        !           524: .nf
        !           525: frank     :   204,     5.000
        !           526: harry     :   209,     4.500
        !           527: bill      :   302,     3.500
        !           528: sam       :   410,    10.000
        !           529: susan     :   100,     0.000
        !           530: sally     :   305,     0.500
        !           531: george    :   302,     4.000
        !           532: 
        !           533: .fi
        !           534: .sp
        !           535: If you wanted a file with the true binary representation
        !           536: of the numbers you would use:
        !           537: .sp
        !           538: .ti +5
        !           539: copy (name = c10, amount = f4, ext = i2)
        !           540: .sp
        !           541: This would create a file with the exact
        !           542: copy of each tuple,
        !           543: one after the other.
        !           544: This is frequently desireable for
        !           545: temporary backup purposes
        !           546: and it guarantees that floating
        !           547: point domains will be exact.
        !           548: .sp 2
        !           549: TYPICAL ERRORS
        !           550: .sp 1
        !           551: There are 17 different errors
        !           552: that can occur in copy.
        !           553: We will go through the most
        !           554: common ones.
        !           555: .sp 1
        !           556: Suppose you have a file with
        !           557: .sp 1
        !           558: bill,3.5,302
        !           559: .br
        !           560: sam,10,410,
        !           561: .br
        !           562: susan,3,100
        !           563: .sp 1
        !           564: and run the copy command
        !           565: .sp 1
        !           566: .in +5
        !           567: .nf
        !           568: copy donation (name = c0, amount = c0, ext = c0)
        !           569:        from "/mnt/bob/data"
        !           570: .fi
        !           571: .in -5
        !           572: .sp 1
        !           573: You would get the error message
        !           574: .sp 1
        !           575: .nf
        !           576: 5809: COPY: bad input string for domain amount. Input was "susan".
        !           577: There were 2 tuples sucessfully copied from /mnt/bob/data into
        !           578: donation.
        !           579: .fi
        !           580: .sp 1
        !           581: What happened is that line 2 had an extra
        !           582: comma.
        !           583: The first two tuples were copied correctly.
        !           584: For the next tuple, name = "" (blank), amount =
        !           585: "susan", and ext = "3".  
        !           586: Since "susan" is not a proper floating point
        !           587: number, an error was generated and
        !           588: processing was stopped after two tuples.
        !           589: .sp 1
        !           590: If you tried to copy the file with a file
        !           591: such as
        !           592: .sp 1
        !           593: nancy,5.0,35000
        !           594: .sp 1
        !           595: you would get the error message
        !           596: .sp 1
        !           597: .nf
        !           598: 5809: COPY: bad input string for domain ext. Input was "35000".
        !           599: There were 0 tuples successfully copied from /mnt/bob/data into
        !           600: donation.
        !           601: .fi
        !           602: .sp 1
        !           603: Here, since ext is an i2 (integer) domain,
        !           604: it cannot exceed the value 32767.
        !           605: .sp 1
        !           606: There are numerous other error messages,
        !           607: most of which are self-explanatory.
        !           608: .sp 1
        !           609: In addition there are three, non-fatal warnings
        !           610: which may appear on a copy "from".
        !           611: .sp 1
        !           612: If you are copying from
        !           613: a file into a relation which
        !           614: is ISAM or hash, a count
        !           615: of the number of duplicate
        !           616: tuples will appear, (if there were
        !           617: any).
        !           618: This will never appear on a "heap"
        !           619: because no duplicate checking
        !           620: is performed.
        !           621: .sp 1
        !           622: INGRES does not allow
        !           623: control characters
        !           624: (such as "bell" etc.)
        !           625: to be stored.
        !           626: If copy reads any control characters, it converts them
        !           627: to blanks and reports the number
        !           628: of domains that had control characters in them.
        !           629: .sp 1
        !           630: If you are copying using the c0
        !           631: option, copy will
        !           632: report if any character strings were
        !           633: longer than their domains
        !           634: and had to be truncated.
        !           635: .sp 2
        !           636: SPECIAL FEATURES
        !           637: .sp 1
        !           638: .ti +3
        !           639: There are a few special functions that
        !           640: make copy a little
        !           641: easier to use
        !           642: .sp 1
        !           643: .nr in 6n
        !           644: .ti -4
        !           645: 1.  Bulk copy
        !           646: .sp 1
        !           647: If you ask for:
        !           648: .sp 1
        !           649: .ti +4
        !           650: copy relname () from "file"
        !           651: .ti +8
        !           652: or
        !           653: .ti +4
        !           654: copy relname () into "file"
        !           655: .sp 1
        !           656: copy expands the statement to mean:
        !           657: .sp 1
        !           658: .in +5
        !           659: copy each domain in its proper
        !           660: order according to its proper
        !           661: format.  
        !           662: .sp 1
        !           663: .in -5
        !           664: So, if you said
        !           665: .sp 1
        !           666: .ti +4
        !           667: copy donation () into "/mnt/bob/donation"
        !           668: .sp 1
        !           669: it would be the same as asking for:
        !           670: .sp 1
        !           671: .ti +4
        !           672: .nf
        !           673: copy donation (name = c10, amount = f4, ext = i2)
        !           674:        into "/mnt/bob/donation"
        !           675: .fi
        !           676: .sp 1
        !           677: This provides a convenient way to copy
        !           678: whole relations to and from INGRES.
        !           679: .sp 1
        !           680: .ti -4
        !           681: 2.  Dummy Domains
        !           682: .sp 1
        !           683: If you are copying data
        !           684: from another computer or program,
        !           685: frequently there will be
        !           686: a portion of data that you will want to
        !           687: ignore.
        !           688: This can be done using the
        !           689: dummy domain specifications
        !           690: d0, d1, d2 ... d511.
        !           691: For example
        !           692: .sp 1
        !           693: .ti +4
        !           694: .nf
        !           695: copy rel (dom1 = c5, dummy = d2, dom2 = i4,
        !           696:        dumb = d0) from "/mnt/me/data"
        !           697: .fi
        !           698: .sp 1
        !           699: The first five characters
        !           700: are put in dom1,
        !           701: the next two characters are ignored.
        !           702: The next four bytes are
        !           703: an i4 (integer) and go in dom2,
        !           704: and the remaining delimited string
        !           705: is ignored.
        !           706: The name given to a dummy specifier is
        !           707: ignored.
        !           708: .sp 1
        !           709: As mentioned previously,
        !           710: dummy domains can be used on a copy
        !           711: "into" a Unix file for inserting
        !           712: special characters.
        !           713: The list of recognizable names includes:
        !           714: .sp 1
        !           715: .in +5
        !           716: .nf
        !           717: nl        newline
        !           718: tab       tab character
        !           719: sp        space
        !           720: nul       a zero byte
        !           721: null      a zero byte
        !           722: comma     ,
        !           723: dash      -
        !           724: colon     :
        !           725: lparen    (
        !           726: rparen    )
        !           727: .fi
        !           728: .in -5
        !           729: .sp 1
        !           730: .ti -4
        !           731: 3.  Truncation
        !           732: .sp 1
        !           733: It is not uncommon to have a mistake occur
        !           734: and need to start over.
        !           735: The simplest way to do that
        !           736: is to "truncate" the relation.
        !           737: This is done by the command:
        !           738: .sp 1
        !           739: .ti +4
        !           740: modify relname to truncated
        !           741: .sp 1
        !           742: This has the effect of removing
        !           743: all tuples in relname,
        !           744: releasing all disk space,
        !           745: and making relname a heap again.
        !           746: It is the logical equivalent of
        !           747: a destroy followed by a create
        !           748: (but with a lot less typing).
        !           749: .sp 1
        !           750: Since formatting mistakes are possible
        !           751: with copy,
        !           752: it is not generally a good idea to
        !           753: copy data into a relation that already
        !           754: has valid data in it.
        !           755: The best procedure is to create a
        !           756: temporary relation with the same domains
        !           757: as the existing relation.
        !           758: Copy data into the temporary relation
        !           759: and then append it to the real relation.
        !           760: For example:
        !           761: 
        !           762: .in +8
        !           763: .nf
        !           764: create tempdom(name=c10,amount=f4,ext=i2)
        !           765: 
        !           766: copy tempdom(name=c0,amount=c0,ext=c0)
        !           767: from "/mnt/bob/data"
        !           768: 
        !           769: range of td is tempdom
        !           770: append to donation(td.all)
        !           771: .fi
        !           772: .in -8
        !           773: .sp 1
        !           774: 4.  Specifing Delimitors.
        !           775: .sp 1
        !           776: Sometimes it is desirable to specify
        !           777: what the delimiting character should be
        !           778: on a copy "from" a file.
        !           779: This can be done by specifing:
        !           780: 
        !           781: .ti +8
        !           782: domain = c0delim
        !           783: 
        !           784: where "delim" is a valid delimitor
        !           785: taken from the list of recognizable names.
        !           786: This list was summarized on the
        !           787: previous page under "dummy domains".
        !           788: For example:
        !           789: 
        !           790: .ti +8
        !           791: copy donation (name = c0nl) from "/mnt/me/data"
        !           792: 
        !           793: will copy names from the file to the relation.
        !           794: Only a new line will delimit the names so
        !           795: any commas or tabs will be passed along as
        !           796: part of the name.
        !           797: 
        !           798: When copying "into" a Unix file,
        !           799: the "delim" is actually written into the
        !           800: file,
        !           801: so on a copy "into" the specification:
        !           802: 
        !           803: .ti +8
        !           804: copy donation (name = c0nl) into "/mnt/me/file"
        !           805: 
        !           806: will cause "name" to be written followed by a new line
        !           807: character.
        !           808: .nr in 0
        !           809: .bp
        !           810: 4.   CHOOSING THE BEST STORAGE STRUCTURES
        !           811: .sp 1
        !           812: .sp
        !           813: We now turn to the issue of efficiency.
        !           814: Once you have created a relation
        !           815: and inserted your
        !           816: data using either copy or append,
        !           817: INGRES can process any query
        !           818: on the relation.
        !           819: There are several things you can do
        !           820: to improve the speed at which INGRES
        !           821: can process a query.
        !           822: .sp
        !           823: INGRES can store a relation in three different
        !           824: internal
        !           825: structures.
        !           826: These are called "heap",
        !           827: "isam", and "hash".
        !           828: First we will briefly describe each
        !           829: structure and then later expand our
        !           830: discussion.
        !           831: .sp
        !           832: HEAP
        !           833: .sp 1
        !           834: When a relation is first created, it is
        !           835: created as a "heap".
        !           836: There are two important properties about a heap:
        !           837: duplicate tuples are not removed,
        !           838: and nothing is known about the location of the tuples.
        !           839: If you ran the query:
        !           840: .sp 1
        !           841: .ti +5
        !           842: range of d is donation
        !           843: .br
        !           844: .ti +5
        !           845: retrieve (d.amount) where d.name = "bill"
        !           846: .sp 1
        !           847: INGRES would have to read every tuple in the
        !           848: relation looking for those with name "bill".
        !           849: If the relation is small this isn't a 
        !           850: serious matter.
        !           851: But if the relation is very large, this can take
        !           852: minutes (or even hours!).
        !           853: .sp 1
        !           854: HASH
        !           855: .sp 1
        !           856: A relation whose structure is "hash" can give fast
        !           857: access to searches on certain domains.
        !           858: (Those domains are usually referred to as
        !           859: "keyed domains".)
        !           860: In addition, a "hashed" relation contains
        !           861: no duplicate tuples.
        !           862: For example, suppose the donation relation is stored hashed on
        !           863: domain "name".  
        !           864: Then the query:
        !           865: .sp 1
        !           866: .ti +5
        !           867: retrieve (d.amount) where d.name = "bill"
        !           868: .sp 1
        !           869: will run quickly
        !           870: since INGRES knows approximately where on
        !           871: disk the tuple is stored.
        !           872: If the relation contains only a few tuples you
        !           873: won't notice the difference between a "heap"
        !           874: and a "hash" structure.
        !           875: But as the relation becomes larger, the
        !           876: difference in speed becomes
        !           877: much more noticeable.
        !           878: .sp 1
        !           879: ISAM
        !           880: .sp 1
        !           881: An isam structure is one where the relation is
        !           882: sorted on one or more domains,
        !           883: (also called keyed domains).
        !           884: Duplicates are also removed on "isam relations".
        !           885: When new tuples are appended they are
        !           886: placed "approximately" in their sorted position in the
        !           887: relation.
        !           888: (The "approximately" will be explained a bit
        !           889: later.)
        !           890: .sp 1
        !           891: Suppose donation is isam on name.
        !           892: To process the query
        !           893: .sp 1
        !           894: .ti +5
        !           895: retrieve (d.amount) where d.name = "bill"
        !           896: .sp 1
        !           897: INGRES will determine where in the sorted order
        !           898: the name "bill" would be and read only
        !           899: those portions of the relation.
        !           900: .sp 1
        !           901: Since the relation is approximately sorted,
        !           902: an isam structure is also efficient for
        !           903: processing the query:
        !           904: .ti +5
        !           905: .sp 1
        !           906: retrieve (d.amount) where d.name >= "b" and d.name < "g"
        !           907: .sp 1
        !           908: This query would retrieve all names beginning
        !           909: with "b" through "f".
        !           910: The entire relation would not have to be
        !           911: searched since it is isam on name.
        !           912: .sp 2
        !           913: SPECIFYING THE STORAGE STRUCTURE
        !           914: .sp
        !           915: Any user created relation can be converted
        !           916: to any storage structure using the
        !           917: "modify" command.
        !           918: For example
        !           919: .sp
        !           920: .ti 5
        !           921: modify donation to hash on name
        !           922: .br
        !           923: or
        !           924: .br
        !           925: .ti 5
        !           926: modify donation to isam on name
        !           927: .sp
        !           928: or even
        !           929: .sp
        !           930: .ti 5
        !           931: modify donation to heap
        !           932: .sp 2
        !           933: PRIMARY AND OVERFLOW PAGES
        !           934: .sp
        !           935: At this point it is necessary to introduce the
        !           936: concepts of primary and overflow pages on
        !           937: hash and isam structures.
        !           938: Both hash and isam are techniques for assigning
        !           939: specific tuples to specific pages of a relation
        !           940: based on the tuple's keyed domains.
        !           941: Thus each page will contain only a certain
        !           942: specified subset of the relation.
        !           943: 
        !           944: When a new tuple is appended to a hash or isam
        !           945: relation, INGRES
        !           946: first determines what page it belongs to,
        !           947: and then looks for room on that page.
        !           948: If there is space then the tuple
        !           949: is placed on that page.
        !           950: If not,
        !           951: then an "overflow" page is created and
        !           952: the tuple is placed there.
        !           953: 
        !           954: The overflow page is linked to the
        !           955: original page.
        !           956: The original page is called the "primary"
        !           957: page.
        !           958: If the overflow page became full,
        !           959: then INGRES
        !           960: would connect an overflow page to it.
        !           961: We would then have one primary page
        !           962: linked to an overflow page,
        !           963: linked to another overflow page.
        !           964: Overflow pages are dynamically added as
        !           965: needed.
        !           966: .sp 2
        !           967: SPECIFYING FREE SPACE
        !           968: .sp
        !           969: The modify command also lets you specify how much
        !           970: room to leave for the relation to grow.
        !           971: As was mentiond in "create",
        !           972: relations are divided into pages.
        !           973: A "fillfactor" can be used to specify how
        !           974: full to make each primary page.
        !           975: This decision should be based
        !           976: only on whether more tuples 
        !           977: will be appended to the relation.
        !           978: For example:
        !           979: .sp
        !           980: .ti 5
        !           981: .nf
        !           982: modify donation to isam on name where fillfactor = 100
        !           983: .fi
        !           984: .sp
        !           985: This tells modify to make each page 100% full
        !           986: if at all possible.
        !           987: .sp
        !           988: .ti 5
        !           989: .nf
        !           990: modify donation to isam on name where fillfactor = 25
        !           991: .fi
        !           992: .sp
        !           993: This will leave each page 25% full or, in other words,
        !           994: 75% empty.
        !           995: We would do this if we had roughly 1/4 of the
        !           996: data already loaded and it was fairly well distributed
        !           997: about the alphabet.
        !           998: .sp
        !           999: Keep in mind that if you don't specify the fillfactor,
        !          1000: INGRES will typically default to a reasonable choice.
        !          1001: Also when a page becomes full, INGRES
        !          1002: automatically creates an "overflow"
        !          1003: page so it is never the case that a relation
        !          1004: will be unable to expand.  
        !          1005: .sp
        !          1006: When modifying a relation
        !          1007: to hash, an additional
        !          1008: parameter "minpages" can
        !          1009: be specified.
        !          1010: Modify will guarantee
        !          1011: that at least "minpage" primary pages will be allocated
        !          1012: for the relation.
        !          1013: .sp
        !          1014: Modify computes how may primary pages will be
        !          1015: needed to store the existing tuples at 
        !          1016: the specified fillfactor
        !          1017: assuming that no overflow pages will be necessary originally.
        !          1018: If that number is less than
        !          1019: minpages, then minpages is used instead.
        !          1020: .sp
        !          1021: For example:
        !          1022: .sp
        !          1023: .ti 5
        !          1024: .nf
        !          1025: modify donation to hash on name where fillfactor = 50,
        !          1026: .ti 10
        !          1027: minpages = 1
        !          1028: .sp 1
        !          1029: .ti 5
        !          1030: modify donation to hash on name where minpages = 150
        !          1031: .fi
        !          1032: .sp
        !          1033: In the first case we guarantee that no more
        !          1034: pages than are necessary will be
        !          1035: used for 50% occupancy.
        !          1036: The second case is typically
        !          1037: used for modifying an empty or near
        !          1038: empty relation.
        !          1039: If the approximate maximum
        !          1040: size of the relation is known in advance,
        !          1041: minpages
        !          1042: can be used to guarantee that the relation will
        !          1043: have its expected maximum size.
        !          1044: .sp
        !          1045: There is one other option available for hash called
        !          1046: "maxpages".
        !          1047: Its syntax is the same as minpages.
        !          1048: It can be used to specify the maximum
        !          1049: number of primary pages to use.
        !          1050: .sp
        !          1051: COMPRESSION
        !          1052: .sp 1
        !          1053: The three storage structures
        !          1054: (heap, hash, isam) can optionally
        !          1055: have "compression" applied
        !          1056: to them.
        !          1057: To do this, refer to the
        !          1058: storage structures as cheap, chash, and cisam.
        !          1059: Compression reduces
        !          1060: the amount of space needed to store each tuple
        !          1061: internally.
        !          1062: The current compression technique is to
        !          1063: suppress trailing blanks in 
        !          1064: character domains.
        !          1065: Using compression will never
        !          1066: require more space and typically
        !          1067: it can save disk space and improve
        !          1068: performance.
        !          1069: Here is an example:
        !          1070: .sp 1
        !          1071: .nf
        !          1072: .ti +5
        !          1073: modify donation to cisam on name where fillfactor = 100
        !          1074: .fi
        !          1075: .sp 1
        !          1076: This will make donation a compressed isam 
        !          1077: structure and fill every page as
        !          1078: full as possible.
        !          1079: With compression, each tuple
        !          1080: can have a different compressed
        !          1081: length.
        !          1082: Thus the number of tuples
        !          1083: that can fit on one page will
        !          1084: depend on how successfully
        !          1085: they can be compressed.
        !          1086: 
        !          1087: Compressed relations can be more expensive to update.
        !          1088: In particular if a replace is done on one or
        !          1089: more domains and the compressed tuple is no
        !          1090: longer the same length,
        !          1091: then INGRES must look for a new place to put the tuple.
        !          1092: .sp 2
        !          1093: TWO VARIATIONS ON A THEME
        !          1094: .sp
        !          1095: As mentioned, duplicates are not removed
        !          1096: from a relation stored
        !          1097: as a heap.
        !          1098: Frequently it is desirable
        !          1099: to remove duplicates and sort
        !          1100: a heap relation.
        !          1101: One way of doing this is to modify the
        !          1102: relation to isam specifying
        !          1103: the order in which to sort
        !          1104: the relation.
        !          1105: An alternative to this is to use either
        !          1106: "heapsort" or "cheapsort".
        !          1107: For example
        !          1108: .sp
        !          1109: .ti 5
        !          1110: .nf
        !          1111: modify donation to heapsort on name, ext
        !          1112: .fi
        !          1113: .sp
        !          1114: This will sort the relation by
        !          1115: name then ext.
        !          1116: The tuples are further sorted on the
        !          1117: remaining domains,
        !          1118: in the order they were listed in the
        !          1119: original create statement.
        !          1120: So in this case the relation will be
        !          1121: sorted on name then ext and then amount.
        !          1122: Duplicate tuples are always removed.
        !          1123: The relation will be left
        !          1124: as a heap.
        !          1125: Heapsort and cheapsort are intended
        !          1126: for sorting a temporary relation before printing and
        !          1127: destroying it.
        !          1128: It is more efficient than modifying
        !          1129: to isam because
        !          1130: with isam INGRES creates a
        !          1131: "directory" containing
        !          1132: key information about each page.
        !          1133: The relation will NOT be kept sorted
        !          1134: when further updates occur.
        !          1135: .sp
        !          1136: Examples:
        !          1137: .sp
        !          1138: .nr in 2n
        !          1139: Here are a collection of examples
        !          1140: and comments as to the efficiency of 
        !          1141: each query.
        !          1142: The queries are based on the
        !          1143: relations:
        !          1144: .(l
        !          1145: parts(pnum, pname, color, weight, qoh)
        !          1146: .br
        !          1147: supply(snum, pnum, jnum, shipdate, quan)
        !          1148: .sp 1
        !          1149: range of p is parts
        !          1150: .br
        !          1151: range of s is supply
        !          1152: .sp 1
        !          1153: modify parts to hash on pnum
        !          1154: .br
        !          1155: modify supply to hash on snum,jnum
        !          1156: .)l
        !          1157: .ti +5
        !          1158: .sp 1
        !          1159: retrieve (p.all) where p.pnum = 10
        !          1160: .sp 1
        !          1161: INGRES will recognize that parts is
        !          1162: hashed on pnum and go directly to the
        !          1163: page where parts with number 10 would be stored.
        !          1164: .sp 1
        !          1165: .ti +5
        !          1166: retrieve (p.all) where p.pname = "tape drive"
        !          1167: .sp 1
        !          1168: INGRES will read the entire relation
        !          1169: looking for matching pnames.
        !          1170: .sp 1
        !          1171: .ti +5
        !          1172: retrieve (p.all) where p.pnum < 10  and p.pnum > 5
        !          1173: .sp 1
        !          1174: INGRES will read the entire relation
        !          1175: because no exact value for pnum
        !          1176: was given.
        !          1177: .sp 1
        !          1178: .ti +5
        !          1179: retrieve (s.shipdate) where s.snum = 471 and s.jnum = 1008
        !          1180: .sp 1
        !          1181: INGRES will recognize that supply is hashed on the
        !          1182: combination of snum and jnum and will go directly
        !          1183: to the correct page.
        !          1184: .ti +5
        !          1185: .sp 1
        !          1186: retrieve (s.shipdate) where s.snum = 471
        !          1187: .sp 1
        !          1188: INGRES will read the entire
        !          1189: relation.
        !          1190: Supply is hashed on the
        !          1191: combination of snum and jnum.
        !          1192: Unless INGRES is given a unique
        !          1193: value for both, it cannot
        !          1194: take advantage of the storage
        !          1195: structure.
        !          1196: .sp 1
        !          1197: .ti +5
        !          1198: retrieve (p.pname, s.shipdate) where
        !          1199: .ti +5
        !          1200: .br
        !          1201: p.pnum = s.pnum and s.snum = 471 and s.jnum = 1008
        !          1202: .sp 1
        !          1203: INGRES will take advantage of both
        !          1204: storage structures.
        !          1205: It will first find all
        !          1206: s.pnum and s.shipdate
        !          1207: where s.snum = 471 and
        !          1208: s.jnum = 1008.
        !          1209: After that it will look for all 
        !          1210: p.pname where p.pnum is equal to
        !          1211: the correct value.
        !          1212: .sp 1
        !          1213: This example illustrates the idea that it is 
        !          1214: frequently a good idea to hash a
        !          1215: relation on the domains where it is
        !          1216: "joined" with another relation.
        !          1217: For example, in this
        !          1218: case it is very common to ask
        !          1219: for p.pnum = s.pnum
        !          1220: .sp 1
        !          1221: To summarize:
        !          1222: .sp 1
        !          1223: To take advantage of a hash
        !          1224: structure,
        !          1225: INGRES needs an exact value
        !          1226: for each key domain.
        !          1227: An exact value is anything
        !          1228: such as:
        !          1229: .ti +5
        !          1230: .sp 1
        !          1231: s.snum = 471
        !          1232: .br
        !          1233: .ti +5
        !          1234: s.pnum = p.pnum
        !          1235: .sp 1
        !          1236: An exact value is not
        !          1237: .sp 1
        !          1238: .ti +5
        !          1239: s.snum >= 471
        !          1240: .br
        !          1241: .ti +5
        !          1242: (s.snum = 10 or s.snum = 20)
        !          1243: .sp 1
        !          1244: Now let's consider some
        !          1245: cases using isam
        !          1246: .sp 1
        !          1247: .in +5
        !          1248: modify supply to isam on snum,shipdate
        !          1249: .br
        !          1250: retrieve (s.all) where s.snum = 471
        !          1251: .br
        !          1252: and s.shipdate > "75-12-31"
        !          1253: .br
        !          1254: and s.shipdate < "77-01-01"
        !          1255: .sp 1
        !          1256: .in -5
        !          1257: Since supply is sorted first on snum and then
        !          1258: on shipdate, INGRES
        !          1259: can take full advantage of the
        !          1260: isam structure to locate the
        !          1261: portions of supply which satisfy
        !          1262: the query.
        !          1263: .sp 1
        !          1264: .ti +5
        !          1265: retrieve (s.all) where s.snum = 47l
        !          1266: .sp 1
        !          1267: Unlike hash, an isam structure
        !          1268: can still be used if only the first key is
        !          1269: provided.
        !          1270: .sp 1
        !          1271: .ti +5
        !          1272: retrieve (s.all) where s.snum > 400 and s.snum < 500
        !          1273: .sp 1
        !          1274: Again INGRES will take advantage of the structure.
        !          1275: .sp 1
        !          1276: .ti +5
        !          1277: retrieve (s.all) where s.shipdate >= "75-12-31" and
        !          1278: .ti +5
        !          1279: s.shipdate <= "77-01-01"
        !          1280: .sp 1
        !          1281: Here INGRES will read the entire relation.
        !          1282: This is because the first key (snum) is not
        !          1283: provided in the query.
        !          1284: .sp 1
        !          1285: To summarize:
        !          1286: .sp 1
        !          1287: Isam can provide improved access
        !          1288: on either exact values or ranges of
        !          1289: values.
        !          1290: It is useful as long as at least
        !          1291: the first key is provided.
        !          1292: .sp 1
        !          1293: To locate where the tuples are
        !          1294: in an isam relation,
        !          1295: INGRES searches the isam directory for that
        !          1296: relation.
        !          1297: When a relation is modified to isam,
        !          1298: the tuples are first sorted and duplicates
        !          1299: are removed.
        !          1300: Next, the relation is
        !          1301: filled (according to the fillfactor) starting
        !          1302: at page 0, 1, 2... for as many
        !          1303: pages as are needed.
        !          1304: .sp 1
        !          1305: Now the directory is built.
        !          1306: The key domains from the first
        !          1307: tuple on each page are collected and
        !          1308: organized into a directory (stored in the relation
        !          1309: on disk).
        !          1310: The directory is never changed
        !          1311: until the next time a modify is done.
        !          1312: .sp 1
        !          1313: Whenever a tuple is added to the relation,
        !          1314: the directory is searched to find
        !          1315: which page the new tuple belongs on.
        !          1316: Within that page, the individual
        !          1317: tuples are NOT kept sorted.
        !          1318: This is what is meant by "approximately" sorted.
        !          1319: .sp 2
        !          1320: .nr in 0
        !          1321: HEAP v. HASH v. ISAM
        !          1322: .sp 1
        !          1323: Let's now compare the relative advantages and disadvantages
        !          1324: of each option.
        !          1325: A relation is always created as a heap.
        !          1326: A heap is the most efficient
        !          1327: structure to use to initially
        !          1328: fill a relation using copy or append.
        !          1329: .sp 1
        !          1330: Space from deleted tuples of a heap
        !          1331: is only reused on the last page.
        !          1332: No duplicate checking is done on
        !          1333: a heap relation.
        !          1334: .sp 1
        !          1335: Hash is advantageous for locating tuples
        !          1336: referenced in a qualification by an exact
        !          1337: value.
        !          1338: The primary page for tuples with a specific
        !          1339: value can be easily computed.
        !          1340: .sp 1
        !          1341: Isam is useful for both exact values and ranges of values.
        !          1342: Since the isam directory must be searched to
        !          1343: locate tuples, it is never as efficient as hash.
        !          1344: .sp 2
        !          1345: OVERFLOW PAGES
        !          1346: .sp 1
        !          1347: When a tuple is to be inserted
        !          1348: and there is no more room on the
        !          1349: primary page of a relation, then an
        !          1350: overflow page is created.
        !          1351: As more tuples are inserted, additional overflow
        !          1352: pages are added as needed.
        !          1353: Overflow pages, while necessary, decrease
        !          1354: the system performance for
        !          1355: retrieves and updates.
        !          1356: .sp 1
        !          1357: For example, let's suppose that supply
        !          1358: is hashed on snum and has 10 primary pages.
        !          1359: Suppose the value snum = 3 falls on page 7.
        !          1360: To find all snum = 3 requires INGRES to search
        !          1361: primary page 7 and all overflow pages of page 7
        !          1362: (if any).
        !          1363: As more overflow pages are added the time
        !          1364: needed to search for
        !          1365: snum = 3 will increase.
        !          1366: Since duplicates are removed on isam and hash,
        !          1367: this search must be performed on appends and
        !          1368: replaces also.
        !          1369: .sp 1
        !          1370: When a hash or isam relation has too many overflow pages
        !          1371: it should be remodified to hash
        !          1372: or isam again.
        !          1373: This will clear up the relation
        !          1374: and eliminate as many overflow pages as possible.
        !          1375: .sp 2
        !          1376: UNIQUE KEYS
        !          1377: .sp 1
        !          1378: When choosing key domains for a relation
        !          1379: it is desirable to have each set of
        !          1380: key domains
        !          1381: as unique as possible.
        !          1382: For example, employee id numbers  
        !          1383: typically have no
        !          1384: duplicate values, while
        !          1385: something like color
        !          1386: is likely to have only a few distinct
        !          1387: values, and something like
        !          1388: sex, to the best of our knowledge, has only two
        !          1389: values.
        !          1390: .sp 1
        !          1391: If a relation is hashed on domain sex then you can expect to have all
        !          1392: males on one primary page and all its
        !          1393: overflow pages and a corresponding
        !          1394: situation with females.
        !          1395: With a hash relation there is no solution to this
        !          1396: problem.
        !          1397: A trade-off must be made between the
        !          1398: most desirable key domains to use in a
        !          1399: qualification versus the uniqueness of the
        !          1400: key values.
        !          1401: .sp 1
        !          1402: Since isam structure can be used if at least
        !          1403: the first key is provided, extra
        !          1404: key domains can sometimes be added to increase uniqueness.
        !          1405: For example, suppose the supply
        !          1406: relation has only 10 unique supplier numbers
        !          1407: but thousands of tuples.
        !          1408: Choosing an isam structure with the keys snum and jnum
        !          1409: will probably give many more unique keys.
        !          1410: However, the directory size will
        !          1411: be larger and consequently it will
        !          1412: take longer to search.
        !          1413: When providing additional keys
        !          1414: just for the sake of increasing
        !          1415: uniqueness,
        !          1416: try to use the smallest possible domains.
        !          1417: .sp 2
        !          1418: SYSTEM RELATIONS
        !          1419: .sp 1
        !          1420: INGRES uses three relations
        !          1421: ("relation", "attribute", and "indexes") to maintain
        !          1422: and organize a data base.
        !          1423: The "relation" relation has one tuple for
        !          1424: each relation in the data base.
        !          1425: The "attribute" relation has one tuple
        !          1426: for each attribute in each
        !          1427: relation.
        !          1428: The "indexes" relation
        !          1429: has one tuple for each secondary
        !          1430: index.
        !          1431: .sp 1
        !          1432: INGRES accesses these relations
        !          1433: in a very well defined manner.
        !          1434: A program called "sysmod" should be used
        !          1435: to modify these relations to hash on the
        !          1436: appropriate domains.
        !          1437: To use sysmod the data base
        !          1438: administrator types
        !          1439: .sp 1
        !          1440: % sysmod data-base-name
        !          1441: .sp 1
        !          1442: Sysmod should be run
        !          1443: initially after the data base is created and subsequently
        !          1444: as relations are created and the data
        !          1445: base grows.
        !          1446: It is insufficient to run
        !          1447: sysmod only once and forget about it.
        !          1448: Rerunning sysmod will cause the
        !          1449: system relations to be remodified.
        !          1450: This will typically remove
        !          1451: most overflow pages and improve
        !          1452: system response time
        !          1453: for everything.
        !          1454: .bp
        !          1455: 5.  SECONDARY INDICES
        !          1456: .sp 1
        !          1457: Using an isam or hash structure
        !          1458: provides a fast way to find
        !          1459: tuples in a relation given values for the key
        !          1460: domains.
        !          1461: Sometimes this is not enough.
        !          1462: For example, suppose we have
        !          1463: the donation relation
        !          1464: .sp 1
        !          1465: .ti +5
        !          1466: donation(name, amount, ext)
        !          1467: .sp 1
        !          1468: hashed on name.
        !          1469: This will provide fast access
        !          1470: to queries where the qualification has
        !          1471: an exact value for name.
        !          1472: What if we also will be doing
        !          1473: queries giving exact values for ext?
        !          1474: .sp 1
        !          1475: Donation can be hashed either on name
        !          1476: or ext, so we would have to choose which is more common
        !          1477: and hash donation on that domain.
        !          1478: The other domain (say ext) can have
        !          1479: a secondary index.
        !          1480: A secondary index is a relation which contains
        !          1481: each "ext" together with the exact
        !          1482: location of where the tuple is in the relation
        !          1483: donation.
        !          1484: .sp 1
        !          1485: The command to create a secondary
        !          1486: index is:
        !          1487: .sp 1
        !          1488: .ti +5
        !          1489: index on donation is donext (ext)
        !          1490: .sp 1
        !          1491: The general format is:
        !          1492: .sp 1
        !          1493: .ti +5
        !          1494: index on relation_name is secondary_index_name (domains)
        !          1495: .sp 1
        !          1496: Here we are asking INGRES
        !          1497: to create a secondary index on the relation
        !          1498: donation.
        !          1499: The domain being indexed is "ext".
        !          1500: Indices are formed in three steps:
        !          1501: .sp 1
        !          1502: .in +4
        !          1503: .ti -5
        !          1504: 1.  "Donext" is created as a heap.
        !          1505: .br
        !          1506: .ti -5
        !          1507: 2.  For each
        !          1508: tuple in donation, a tuple is inserted
        !          1509: in "donext" with the value for ext and the
        !          1510: exact location of the corresponding tuple in
        !          1511: donation.
        !          1512: .br
        !          1513: .ti -5
        !          1514: 3.  By default "donext" is modified to isam.
        !          1515: .in -4
        !          1516: .sp 1
        !          1517: Now if you run the query
        !          1518: .sp 1
        !          1519: .ti +5
        !          1520: range of d is donation
        !          1521: .ti +5
        !          1522: retrieve(d.amount) where d.ext = 207
        !          1523: .sp 1
        !          1524: INGRES will automatically look first in
        !          1525: "donext" to find ext = 207.
        !          1526: When it finds one it then goes directly
        !          1527: to the tuple in the donation relation.
        !          1528: Since "donext" is isam on ext, search for
        !          1529: ext = 207 can typically be
        !          1530: done rapidly.
        !          1531: .sp 1
        !          1532: If you run the query
        !          1533: .sp 1
        !          1534: .ti 5
        !          1535: retrieve(d.amount) where d.name = "frank"
        !          1536: .sp 1
        !          1537: then INGRES will continue to use the hash
        !          1538: structure of the relation "donation"
        !          1539: to locate the qualifying tuples.
        !          1540: .sp 1
        !          1541: Since secondary indices are themselves relations,
        !          1542: they also can be either hash, isam, chash or cisam.
        !          1543: It never makes sense to a secondary index a heap.
        !          1544: .sp 1
        !          1545: The decision as to what structure to make
        !          1546: them on involves the same issues
        !          1547: as were discussed before:
        !          1548: .sp 1
        !          1549: Will the domains be referenced by exact value?
        !          1550: .br
        !          1551: Will they be referenced by ranges of value?
        !          1552: .br
        !          1553: etc.
        !          1554: .sp 1
        !          1555: In this case the "ext" domain
        !          1556: will be referenced by exact values, and
        !          1557: since the relation is nearly full we will do:
        !          1558: .sp 1
        !          1559: .ti +5
        !          1560: modify donext to hash on ext where fillfactor = 100
        !          1561: .ti +5
        !          1562: and minpages = 1
        !          1563: .sp 1
        !          1564: Secondary indices provide a way for INGRES
        !          1565: to access tuples based on domains
        !          1566: that are not key domains.
        !          1567: A relation can have any number of secondary
        !          1568: indices and in addition
        !          1569: each secondary index can be an index
        !          1570: on up to six domains of the primary relation.
        !          1571: .sp 1
        !          1572: Whenever a tuple is replaced, deleted
        !          1573: or appended to a primary relation,
        !          1574: all secondary indices must
        !          1575: also be updated.  
        !          1576: Thus secondary indices
        !          1577: are "not free". 
        !          1578: They increase
        !          1579: the cost of updating the
        !          1580: primary relation, but
        !          1581: can decrease the cost of finding tuples
        !          1582: in the primary relation.
        !          1583: .sp 1
        !          1584: Whether a secondary index will improve
        !          1585: performance or not strongly
        !          1586: depends on the uniqueness of the
        !          1587: values of the domains being
        !          1588: indexed.
        !          1589: The primary concern is whether searching
        !          1590: through the secondary index is
        !          1591: more efficient than simply
        !          1592: reading the entire primary relation.
        !          1593: In general it is if the
        !          1594: number of tuples which satisfy the
        !          1595: qualification is less than the number of total pages
        !          1596: (both primary and overflow) in the primary
        !          1597: relation.
        !          1598: .sp 1
        !          1599: For example if we frequently want to find
        !          1600: all people who donated less than
        !          1601: five dollars, consider creating
        !          1602: .sp 1
        !          1603: .ti +5
        !          1604: index on donation is donamount (amount)
        !          1605: .sp 1
        !          1606: By default donamount will be isam
        !          1607: on amount.
        !          1608: IF INGRES processes the query:
        !          1609: .sp 1
        !          1610: .ti +5
        !          1611: retrieve(d.name) where d.amount < 5.0
        !          1612: .sp 1
        !          1613: it will locate d.amount < 5.0 in the secondary
        !          1614: index and for each tuple it
        !          1615: finds will fetch the corresponding
        !          1616: tuple in donation.
        !          1617: The tuples in donamount are sorted by
        !          1618: amount but the tuples
        !          1619: in donation are not.
        !          1620: Thus in general each tuple fetch from
        !          1621: donation via donamount will be on a
        !          1622: different page.
        !          1623: Retrieval using the secondary index can then cause more page
        !          1624: reads than simply reading all of donation sequentially!
        !          1625: So in this example it would
        !          1626: be a bad idea to create the secondary
        !          1627: index.
        !          1628: .bp
        !          1629: 6.  RECOVERY AND DATA UPDATE
        !          1630: .sp 1
        !          1631: INGRES has been carefully designed
        !          1632: to protect the integrity of a data base
        !          1633: against certain classes
        !          1634: of system failures.
        !          1635: To do this INGRES
        !          1636: processes changes to a relation
        !          1637: using what we call "deferred
        !          1638: update" or "batch file update".
        !          1639: In addition there are two INGRES
        !          1640: programs "restore" and "purge" that can be used to check
        !          1641: out a data base after a system failure.
        !          1642: We will first discuss how deferred updates are created
        !          1643: and processed, and second we will discuss
        !          1644: the use of purge and restore.
        !          1645: .sp 1
        !          1646: DEFERRED UPDATE (Batch update)
        !          1647: .in +4
        !          1648: .sp 1
        !          1649: .ti -5
        !          1650: An append, replace or delete command is run in four steps:
        !          1651: .sp 1
        !          1652: .ti -5
        !          1653: 1.  An empty batch file is created.
        !          1654: .ti -5
        !          1655: 2.  The command is run to completion
        !          1656: and each change to the result relation is written into
        !          1657: the batch file.
        !          1658: .ti -5
        !          1659: 3.  The batch file is read and the
        !          1660: relation and its secondary indices (if any)
        !          1661: are actually updated.
        !          1662: .ti -5
        !          1663: 4.  The batch file is destroyed and INGRES
        !          1664: returns back to the user.
        !          1665: .sp 1
        !          1666: .in -4
        !          1667: Deferred update defers all actual
        !          1668: updating until the very end of
        !          1669: the query.
        !          1670: There are three advantages to doing this.
        !          1671: .sp 1
        !          1672: l.  Provides recovery from system failures
        !          1673: .sp 1
        !          1674: If the system "crashes" during an update,
        !          1675: the INGRES recovery program will decide to either
        !          1676: run the update to completion or else
        !          1677: "back out" the update, leaving the
        !          1678: relation as it looked before the update
        !          1679: was started.
        !          1680: .sp 1
        !          1681: 2.  Prevents infinite queries
        !          1682: .sp 1
        !          1683: If "donation" were a heap and the query
        !          1684: .sp 1
        !          1685: .ti +4
        !          1686: range of d is donation
        !          1687: .ti +4
        !          1688: append to donation(d.all)
        !          1689: .sp 1
        !          1690: were run without deferred update,
        !          1691: it would terminate only when it ran
        !          1692: out of space on disk!
        !          1693: This is because INGRES would start reading the
        !          1694: relation from the beginning and
        !          1695: appending each tuple at the end.
        !          1696: It would soon start reading the tuples it
        !          1697: had just previously appended and
        !          1698: continue indefinitely to
        !          1699: "chase its tail".
        !          1700: .sp 1
        !          1701: While this query is certainly not
        !          1702: typical, it illustrates the point.
        !          1703: There are certain classes of queries
        !          1704: where problems occur if WHEN
        !          1705: an update actually occurs
        !          1706: is not precisely defined.
        !          1707: With deferred update we can
        !          1708: guarantee consistent and logical
        !          1709: results.
        !          1710: .sp 1
        !          1711: 3.  Speeds up processing of secondary indices
        !          1712: .sp 1
        !          1713: Secondary indices can be updated
        !          1714: faster if they are done one at a time
        !          1715: instead of all at once.
        !          1716: It also insures protection against
        !          1717: the secondary index becoming inconsistent
        !          1718: with its primary relation.
        !          1719: .sp 1
        !          1720: TURNING DEFERRED UPDATE OFF
        !          1721: .sp 1
        !          1722: If you are not persuaded by any of
        !          1723: these arguments, INGRES
        !          1724: allows you to turn deferred update off!
        !          1725: Indeed there are certain cases when
        !          1726: it is appropriate (although
        !          1727: certainly not essential) to perform
        !          1728: updates directly, that is, the relation is updated
        !          1729: while the query is being processed.
        !          1730: .sp 1
        !          1731: To use direct update, you must be given
        !          1732: permission by the INGRES
        !          1733: super user.
        !          1734: Then when invoking INGRES
        !          1735: specify the "-b" flag which turns
        !          1736: off batch update.
        !          1737: .sp 1
        !          1738: .ti +4
        !          1739: % ingres mydate -b
        !          1740: .sp 1
        !          1741: INGRES will use direct update on any relation without
        !          1742: secondary indices.  
        !          1743: It will still silently use
        !          1744: deferred update if a relation
        !          1745: has any secondary indices.
        !          1746: By using the "-b" flag you are
        !          1747: sacrificing points 1 and 2 above.
        !          1748: In most cases you SHOULD NOT
        !          1749: use the -b flag.
        !          1750: .sp 1
        !          1751: If you are using INGRES
        !          1752: to interactively enter
        !          1753: or change one tuple at
        !          1754: a time, it is slightly
        !          1755: more efficient to have deferred
        !          1756: update turned off.
        !          1757: If the system crashes during an
        !          1758: update the person entering the data
        !          1759: will be aware of the situation
        !          1760: and can check whether the tuple
        !          1761: was updated or not.
        !          1762: .sp 1
        !          1763: RESTORE
        !          1764: .sp 1
        !          1765: INGRES is designed to recover
        !          1766: from the common types of system
        !          1767: crashes which leave the Unix file
        !          1768: system intact.
        !          1769: It can recover from updates, creates,
        !          1770: destroys, modifies and index commands.
        !          1771: .sp 1
        !          1772: INGRES is designed to "fail safe".
        !          1773: If any inconsistancies are
        !          1774: discovered or any failures
        !          1775: are returned from Unix,
        !          1776: INGRES will generate a system error
        !          1777: message (SYSERR) and exit.
        !          1778: .sp 1
        !          1779: Whenever Unix crashes while INGRES
        !          1780: is running or whenever an INGRES
        !          1781: syserr occurs, it is
        !          1782: generally a good idea to have the date
        !          1783: base administrator run the command
        !          1784: .sp 1
        !          1785: .ti +5
        !          1786: % restore data_base_name
        !          1787: .sp 1
        !          1788: The restore program performs the
        !          1789: following functions:
        !          1790: .in +4
        !          1791: .sp 1
        !          1792: .ti -5
        !          1793: 1.  Looks for batch update files.
        !          1794: If any are found, it examines each
        !          1795: one to see if it is complete.
        !          1796: If the system crash occured while
        !          1797: the batch file was being read
        !          1798: and the data base being updated,
        !          1799: then restore will complete
        !          1800: the update.
        !          1801: Otherwise the batch file was not
        !          1802: completed and it is simply destroyed;
        !          1803: the effect is as though the query had never been run.
        !          1804: .sp 1
        !          1805: .ti -5
        !          1806: 2.  Checks for uncompleted modify commands.
        !          1807: This step is crucial.
        !          1808: It guarantees that you will either have the
        !          1809: relation as it existed before
        !          1810: the modify, or restore will complete
        !          1811: the modify command.
        !          1812: Modify works by creating a new copy
        !          1813: of the relation in the new structure.
        !          1814: Then when it is ready to replace the old
        !          1815: relation, it stores the new information in a
        !          1816: "modify batch file".  
        !          1817: This enables restore to determine the state of
        !          1818: uncompleted modifies.
        !          1819: .sp 1
        !          1820: .ti -5
        !          1821: 3.  Checks consistency of system
        !          1822: relations.
        !          1823: This check is used to complete "destory"
        !          1824: commands, back out "create" commands,
        !          1825: and back out or complete "index"
        !          1826: commands that were interrupted by a
        !          1827: system crash.
        !          1828: .sp 1
        !          1829: .ti -5
        !          1830: 4.  Purges temporary relations and files.
        !          1831: Restore executes the "purge" program to
        !          1832: remove temporary relations and temporary
        !          1833: files created by the system.
        !          1834: Purge will be discussed in more detail a bit later.
        !          1835: .in -4
        !          1836: .sp 1
        !          1837: Restore cannot tell the user which queries have run and
        !          1838: which have not.
        !          1839: It can only identify those queries which were in the
        !          1840: process of being run when the crash occured.
        !          1841: When batching queries together,
        !          1842: it is a good idea to save the output in a file.
        !          1843: By having the monitor print out each query or set of
        !          1844: queries,
        !          1845: the user can later identify which queries were run.
        !          1846: .sp 1
        !          1847: Restore has several options to increase its
        !          1848: usability.
        !          1849: They are specified by "flags".
        !          1850: The options include:
        !          1851: .sp 1
        !          1852: .in +4
        !          1853: .nf
        !          1854: -a            ask before doing anything
        !          1855: -f            passed to purge. used to remove temporary files.
        !          1856: -p            passed to purge.  used to destory expired rela-
        !          1857:               tions.
        !          1858: no database   restores all data bases for which you are the
        !          1859:               dba.
        !          1860: .fi
        !          1861: .in -4
        !          1862: .sp 1
        !          1863: Of these options the "-a" is the most
        !          1864: important.
        !          1865: It can happen that a Unix crash can cause a page of
        !          1866: the system catalogues to be
        !          1867: incorrect.
        !          1868: This might cause restore to destory
        !          1869: a relation.
        !          1870: In fact, you might want
        !          1871: to "patch" the system relations to correct
        !          1872: the problem.
        !          1873: No restore program can account
        !          1874: for all possibilities.
        !          1875: It is therefore no replacement
        !          1876: (fortunately) for a human.
        !          1877: .sp 1
        !          1878: If "-a" is specified, restore
        !          1879: will state what it wants to do and then ask
        !          1880: for permission.
        !          1881: It reads standard input and
        !          1882: accepts "y" to mean go ahead and anything
        !          1883: else to mean no.
        !          1884: For example, to have restore ask you before
        !          1885: doing anything
        !          1886: .sp 1
        !          1887: .ti +5
        !          1888: restore -a mydatabase
        !          1889: .sp 1
        !          1890: To have it take "no" for all its questions
        !          1891: .sp 1
        !          1892: .ti +5
        !          1893: restore -a mydatabase </dev/null
        !          1894: .sp 1
        !          1895: Using the -a flag,
        !          1896: restore might ask for permission
        !          1897: to perform some cleanup;
        !          1898: for example,
        !          1899: if it finds an attribute for which there
        !          1900: is no corresponding relation,
        !          1901: or if it finds a secondary index for which
        !          1902: there is no primary relation,
        !          1903: etc.
        !          1904: .sp 1
        !          1905: To date, we have never had a system
        !          1906: crash which INGRES
        !          1907: could not recover from.
        !          1908: This does not mean that it will never happen, but
        !          1909: rather that it shouldn't
        !          1910: be too great 
        !          1911: a concern for you.
        !          1912: It should be mentioned that restore is not
        !          1913: a substitution for doing periodic
        !          1914: backing up, nor does it
        !          1915: ever perform such a function.
        !          1916: .sp 1
        !          1917: PURGE
        !          1918: .sp 1
        !          1919: Purge can be used to report expired relations,
        !          1920: destroy temporary system relations,
        !          1921: remove extraneous files,
        !          1922: and destory expired relations.
        !          1923: To use purge you must be the DBA
        !          1924: for the data base.
        !          1925: .sp 1
        !          1926: .ti +5
        !          1927: % purge mydatabase
        !          1928: .sp 1
        !          1929: Purge has several options which are
        !          1930: specified by flags which are
        !          1931: worth noting:
        !          1932: .nr in 4n
        !          1933: .sp 1
        !          1934: .nf
        !          1935: -f   (default is off) remove all extraneous files.
        !          1936:      Each file is reported and then removed.  If "-f"
        !          1937:      is not specified then the file is only reported.
        !          1938: .sp 1
        !          1939: -p   (default is off) destroy all expired relations.
        !          1940:      Each expired relation is reported and if "-p"
        !          1941:      was specified the relation is destroyed.
        !          1942: .fi
        !          1943: .nr in 0
        !          1944: .sp 1
        !          1945: Purge always destroys relations and files
        !          1946: which are known to be INGRES
        !          1947: system temporaries.
        !          1948: When processing multi-variable
        !          1949: queries and queries with aggregate functions, 
        !          1950: INGRES will usually create temporary relations
        !          1951: with intermediate results.
        !          1952: These relations always begin with the
        !          1953: characters "_SYS".  
        !          1954: Other INGRES commands create temporary files which also
        !          1955: begin with "_SYS".
        !          1956: Under normal processing they are
        !          1957: always destroyed. 
        !          1958: If a system crash occurs, they might be left.
        !          1959: Purge will always clean up the temporary
        !          1960: system files.
        !          1961: It cleans up the user relations only
        !          1962: when specifically asked to.

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.