There is no absolute answer, because it depends on the attack model. By truncating the hash, you make some operations easier; this is bad if the attacker wants to perform these operations, and making them easier actually makes them feasible.
There are three main characteristics that cryptographic hash functions try to fulfil:
- Resistance to preimages: given x, it should be infeasible to find m such that h(m) = x.
- Resistance to second preimages: given m, it should be infeasible to find m' ≠ m such that h(m) = h(m').
- Resistance to collisions: it should be infeasible to find m' ≠ m such that h(m) = h(m').
For a perfect hash function that has an output of n bits, costs of finding preimages, second preimages or collisions will be, respectively, 2n, 2n and 2n/2. By truncating the hash output, you lower these costs correspondingly. As a rule of thumb, a cost of 264 is very hard (feasible, but it takes more than a dozen PC) and 280 is infeasible.
In your case, if a collision is interesting for the attacker, and he gets to choose what is hashed, then the attacker will try to input two data elements that imply a hash collision (on your truncated hash). Truncating to 12 bytes makes the attack quite feasible, easy if you go down to 8 bytes. On the other hand, if all the attacker can do is to try to find some data element matching a given truncated hash (second preimage), then at 10 or 12 bytes this is still too hard to be feasible, and at 8 bytes it is merely "very expensive" (so probably not worth the effort).
If there is no attacker and you are just fighting bad luck, then truncating to 8 bytes incurs the risk of spurious collisions; you should reach your first collision after (on average) entering a few billions of entries. Depending on your situation, this may or may not be tolerable.