A razão pela qual os números primos são usados é minimizar colisões quando os dados exibem alguns padrões particulares.
Primeiras coisas primeiro: se os dados são aleatórios, não há necessidade de um número primo, você pode fazer uma operação mod contra qualquer número e terá o mesmo número de colisões para cada valor possível do módulo.
Mas quando os dados não são aleatórios, coisas estranhas acontecem. Por exemplo, considere dados numéricos sempre múltiplos de 10.
Se usarmos o mod 4, encontramos:
10 mod 4 = 2
20 mod 4 = 0
30 mod 4 = 2
40 mod 4 = 0
50 mod 4 = 2
Portanto, dos 3 valores possíveis do módulo (0,1,2,3), apenas 0 e 2 terão colisões, o que é ruim.
Se usarmos um número primo como 7:
10 mod 7 = 3
20 mod 7 = 6
30 mod 7 = 2
40 mod 7 = 4
50 mod 7 = 1
etc
Também observamos que 5 não é uma boa escolha, mas 5 é primo, o motivo é que todas as nossas chaves são múltiplas de 5. Isso significa que temos que escolher um número primo que não divida nossas chaves, escolher um número primo grande é geralmente o suficiente.
Portanto, errar por ser repetitivo é a razão pela qual os números primos são usados para neutralizar o efeito dos padrões nas chaves na distribuição de colisões de uma função hash.