Aquí hay varias cosas que me gustaría probar, en orden creciente de dificultad:
(más fácil) - Asegúrese de que tiene el derecho cubriendo índice de
CREATE INDEX ix_temp ON relations (relation_title, object_title);
Esto debería maximizar el rendimiento dado su esquema existente, ya que (a menos que su versión del optimizador mySQL sea realmente tonta) minimizará la cantidad de E/S necesarias para satisfacer su consulta (a diferencia de si el índice está en el orden inverso donde el total el índice debe escanearse) y cubrirá la consulta para que no tenga que tocar el índice agrupado.
(un poco más difícil) - asegúrese de que sus campos varchar son lo más pequeño posible
Uno de los retos Potencia con índices varchar en MySQL es que, cuando se procesa una consulta, el declarada tamaño completo de la el campo será arrastrado a la RAM. Por lo tanto, si tiene un varchar (256) pero solo usa 4 caracteres, todavía está pagando el uso de 256 bytes de RAM mientras se procesa la consulta. ¡Ay! Entonces, si puede reducir sus límites de varchar fácilmente, esto debería acelerar sus consultas.
(más duro) - Normalizar
30% de sus filas que tienen un único valor de cadena es un claro grito de normalización en otra tabla lo que no está duplicando cadenas millones de veces. Considere la posibilidad de normalizar en tres tablas y usar ID enteros para unirlas.
En algunos casos, puede normalizar bajo las cubiertas y ocultar la normalización con vistas que coinciden con el nombre de la tabla actual ... entonces solo necesita hacer que sus consultas INSERT/UPDATE/DELETE sean conscientes de la normalización pero puede deja tus SELECT solo.
(el más duro) - Hash sus columnas de cadena y el índice de los hashes
Si los medios que cambian demasiado código normalización, pero puede cambiar su esquema un poco, es posible que desee considerar la creación de hash de 128 bits para sus columnas de cadena (usando el MD5 function). En este caso (a diferencia de la normalización) no tiene que cambiar todas sus consultas, solo los INSERT y algunos de los SELECT. De todos modos, querrá actualizar sus campos de cadena y luego crear un índice en los hash, p.
CREATE INDEX ix_temp ON relations (relation_title_hash, object_title_hash);
Tenga en cuenta que tendrá que jugar con el SELECT para asegurarse de que está haciendo el cálculo a través del índice hash y no tirando en el índice agrupado (necesario para resolver el valor del texto de object_title con el fin para satisfacer la consulta).
Además, si relation_title tiene un tamaño pequeño pero varchar título objeto tiene un tamaño de largo, a continuación, que potencialmente puede desmenuzar única object_title y crear el índice en (relation_title, object_title_hash)
.
Tenga en cuenta que esta solución solo ayuda si uno o ambos de estos campos es muy largo en relación con el tamaño de los hash.
También tenga en cuenta que hay interesantes efectos de intercalación/intercalación de hashing, ya que el hash de una cadena en minúscula no es lo mismo que el hash de una letra mayúscula. Por lo tanto, deberá asegurarse de aplicar la canonicalización a las cadenas antes de mezclarlas. En otras palabras, solo hash minúsculas si está en una base de datos insensible a mayúsculas y minúsculas. También es posible que desee recortar espacios desde el principio hasta el final, dependiendo de cómo maneje su DB los espacios iniciales/finales.
¿Podría proporcionar más detalles, por ejemplo? todo el Select y la estructura de la tabla? Otra primera oportunidad: ¿Está utilizando correctamente los índices? – Kosi2801
Agregué algunas posibles soluciones a continuación, pero estoy de acuerdo con Kosi en que la definición de tablas (¡especialmente la longitud de las columnas varchar!) Y las definiciones de índices serían muy útiles para diagnosticar esto. –
¿Las relaciones son una tabla Innodb o MyISAM? –