True. Don't be apprehensive about depth/complexity. A comment line or two may be sufficient to document the structure if you need to go back and tweak it. Here's a one line comment from something I wrote several months ago.
This is sufficient to remind me how the data is organized. Polls are polling cycles over time for chip insertion machines which may have one or two lanes/stages. The row/col are defined by a header row of words for the column labels. Values corresponding to those header row words are in subsequent rows.
This also illustrates one thing I frequently do. I often use and store my hashes and arrays as refs. This makes it easy to pass everything as a scaler. For example, I have one package to handle the processing of one part of the data. If I need to store that, I just get and store the ref to combine the individual pieces to a higher level. This type of organization allows the use of OO concepts others have mentioned, but does not break/remove the built-in features for using arrays or hashes. If all of your data is in one file, this may not be needed. But, it is a handy pattern that can be used in other situations.