No estoy seguro de cómo funciona todo internamente, pero dependiendo de la situación, recomendaría jugar con una tabla que 'despliega' todos los valores de d1 y luego se une a ese. De esta forma, el motor de consulta puede identificar el registro correcto 'exactamente' en lugar de tener que encontrar una combinación de límites que coincidan con el valor que se busca.
por ejemplo
x value
a 1
a 2
a 3
b 5
b 6
b 7
b 8
b 9
b 10
b 11
c 19 etc..
dado un índice en la columna de valor (**), esto debería ser un poco más rápido que unirse con BETWEEN start AND end en la tabla d1 original en mi humilde opinión.
Por supuesto, cada vez que realice cambios en d1, también deberá ajustar la tabla desplegable (¿activador?). Si esto sucede con frecuencia, pasará más tiempo actualizando la tabla implementada que el que ganó en primer lugar. Además, esto puede ocupar bastante espacio (en disco) rápidamente si algunos de los intervalos son realmente grandes; y también, esto supone que no necesitamos buscar números no enteros (por ejemplo, ¿qué pasa si buscamos el valor 3.14?)
(Puede considerar experimentar con uno único en (valor, x) aquí...)