The structure of a MIBs internals are a little strange and foreign at first, but it's structured well
enough that you can poke through it pretty intelligently without really knowing what your doing.
The structure of a MIB comes from the Structure of Management Information (SMI) standard detailed in IETF RFC 1155 and 2578.
If you choose to modify or write your own MIBs you'll benefit from understanding SMI before hacking much
on MIBs.

Lets look at the header of a MIB to get a better idea of how they work:

Comments can be inserted into a MIB by prepending them with two dashes. In the header
the declaration BEGIN starts off the MIB. Imports can be used to pull information
from other MIBs, typically those mandated by the MIB-II standard.

The MIB lays out the structure of OID addresses starting from the enterprises value.
Here the enterprise value 318 maps to "apc" (relative address .1.318). Typically
then several categories are defined. Here we see 2 categories: products (.1.318.1) and
apcmgmt (.1.318.2). Notice that in the curly braces two values are specified, its parent
address followed by its address. So the products identifier is parented by the
apc identifier which is parented by the enterprises identifier, so on
and so forth. This type of categorization and subcategorizing will typically continue
on in the header of the MIB for awhile segmenting the available keys into tight subgroupings.
By segmenting values out in this way it makes the available keys easier to navigate.

The real meat of the MIB is in the description of object types. Here's
an example of a integer key:

upsBasicOutputStatus OBJECT-TYPE
SYNTAX INTEGER {
unknown(1),
onLine(2),
onBattery(3),
onSmartBoost(4),
timedSleeping(5),
softwareBypass(6),
off(7),
rebooting(8),
switchedBypass(9),
hardwareFailureBypass(10),
sleepingUntilPowerReturn(11),
onSmartTrim(12)
}
ACCESS read-only
STATUS mandatory
DESCRIPTION
"The current state of the UPS. If the UPS is unable
to determine the state of the UPS this variable is set
to unknown(1)."
::= { upsBasicOutput 1 }

Here is defined the upsBasicOutputStatus key with a return type of INTEGER. The
returned integer maps to one of 12 different return values as listed. Notice
that in the MIB a description of the key is provided. These descriptions can be
extremely useful in determining which objects can best provide the data you want,
especially if you don't have MIB documentation supplied by the vendor.

Notice also that the last line of the object type description includes the numeric value 1
with upsBasicOutput as the parent. If we follow this parenting backwards in the MIB
we'd find that upsBasicOutput has the value 1 and is parented by upsOutput which has the value
4 and is parented by ups which has a value of 1, which is parented by hardware which has a
value of 1, which is parented by products with a value of 1 which is parented by apc with a value of
318, which is parented by enterprises with a value of 1. So, if we put all that mapping together
we get a relative address for the key upsBasicOutputStatus of .1.318.1.1.1.4.1.1.0. Remember
that the trailing .0 represents the first instance of the key. Applications called MIB Browsers
can easily parse a MIB and make navigation much quicker than flipping through the file in vim, but
don't be fooled into thinking it's difficult without such a tool.

So, whats really important to notice here is that the MIB is really just providing us with a
road map of the OIDs available on the agent we wish to get values from. A MIB describes both
where to find a value and what it returns. We can still interface with a device without the MIB,
it's just much easier when you get a return of "Up" instead of "1". By leveraging the options
of the Net-SNMP CLI tools you can decide just how you wish to return output which will be different
if your just using the tool from the command line (where "Up" is preferable) or if your calling
the tool from a script (where "1" is preferable).