A method for reading a data segment of a logical block of data from a heterogeneous data volume (200, 300, 400, 505, 607, 700, 1013), the method comprising: receiving a read operation to read the data segment from the heterogeneous data volume (200, 300, 400, 505, 607, 700, 1013), wherein: a first redundant copy of the data segment is stored in a first class of storage and a second redundant copy of the data segment is stored in a second class of storage; characterized by: in response to receiving the read operation: determining a first read preference value for the first redundant copy of the data segment based on a first number of input/output operations currently pending at the first class of storage; determining a second read preference value for the second redundant copy of the data segment based on a second number of input/output operations currently pending at the second class of storage; selecting one of the first and the second redundant copies of the data segment based on the first and the second read preference values; and retrieving the selected redundant copy of the data segment. receiving a read operation to read the data segment from the heterogeneous data volume (200, 300, 400, 505, 607, 700, 1013), wherein: a first redundant copy of the data segment is stored in a first class of storage and a second redundant copy of the data segment is stored in a second class of storage; a first redundant copy of the data segment is stored in a first class of storage and a second redundant copy of the data segment is stored in a second class of storage; characterized by: in response to receiving the read operation: determining a first read preference value for the first redundant copy of the data segment based on a first number of input/output operations currently pending at the first class of storage; determining a second read preference value for the second redundant copy of the data segment based on a second number of input/output operations currently pending at the second class of storage; selecting one of the first and the second redundant copies of the data segment based on the first and the second read preference values; and retrieving the selected redundant copy of the data segment. in response to receiving the read operation: determining a first read preference value for the first redundant copy of the data segment based on a first number of input/output operations currently pending at the first class of storage; determining a second read preference value for the second redundant copy of the data segment based on a second number of input/output operations currently pending at the second class of storage; selecting one of the first and the second redundant copies of the data segment based on the first and the second read preference values; and retrieving the selected redundant copy of the data segment. determining a first read preference value for the first redundant copy of the data segment based on a first number of input/output operations currently pending at the first class of storage; determining a second read preference value for the second redundant copy of the data segment based on a second number of input/output operations currently pending at the second class of storage; selecting one of the first and the second redundant copies of the data segment based on the first and the second read preference values; and retrieving the selected redundant copy of the data segment.