2012-05-22 20 views
17

Estamos teniendo algunos problemas extraños con las uniones internas de MySQL. Básicamente, obtenemos un error extraño cuando usamos un operador '=', pero usar 'like' en su lugar lo hace funcionar. Desafortunadamente, esto es a través de ActiveRecord y no es una manera fácil de dar un "Me gusta" allí, además queremos entender qué está pasando realmente aquí.MySQL INNER JOIN - '=' vs 'like'

Ésta es la consulta que falla:

mysql> SELECT COUNT(*) FROM `versions` INNER JOIN `site_versions` 
       ON `versions`.id = `site_versions`.version_id; 

Aquí está el error:

ERROR 1296 (HY000): Got error 20008 'Query aborted due to out of query memory' 
from NDBCLUSTER 

Ésta es la consulta que funciona:

mysql> SELECT COUNT(*) FROM `versions` INNER JOIN `site_versions` 
       ON `versions`.id like `site_versions`.version_id; 

Aquí están algunos detalles sobre la las tablas mismas:

mysql> desc site_versions; 
+----------------------+----------+------+-----+---------+----------------+ 
| Field    | Type  | Null | Key | Default | Extra   | 
+----------------------+----------+------+-----+---------+----------------+ 
| id     | int(11) | NO | PRI | NULL | auto_increment | 
| version_id   | int(11) | YES | MUL | NULL |    | 
[..snip..] 
+----------------------+----------+------+-----+---------+----------------+ 

mysql> desc versions; 
+------------+--------------+------+-----+---------+----------------+ 
| Field  | Type   | Null | Key | Default | Extra   | 
+------------+--------------+------+-----+---------+----------------+ 
| id   | int(11)  | NO | PRI | NULL | auto_increment | 
[..snip..] 
+------------+--------------+------+-----+---------+----------------+ 

¿Alguna idea de por qué el 'me gusta' funciona y el '=' no?

+4

¿de hecho está dando los resultados que espera? tal vez es simplemente no unirse a nada (porque ¿qué significa mean para ints?) y así evitar el problema de memoria que la consulta válida está desencadenando. –

+1

@andrewcooke - Hmm, 'like' parece funcionar cuando se usa de esta manera: http://sqlfiddle.com/#!2/86792/1 –

+3

También podría ayudar la pregunta para mostrar la 'explicación' de cada consulta. –

Respuesta

0

No estoy seguro de si esto solucionará su problema, pero es posible. No use count(*). Tal vez se está "confundiendo" acerca de qué contar. Es una buena práctica contar un campo específico, p. id. Para hacer esto, necesita usar un alias para las tablas.

SELECT COUNT(v.id) FROM versions as v 
INNER JOIN site_versions as sv ON v.id = sv.version_id; 
+1

O simplemente use una constante: 'SELECT COUNT (1) FROM ...' – bjnord

+4

En una situación inusual como los OP, no debe sorprenderse demasiado las sugerencias como la suya. Y no seré. Pero esta afirmación: * 'Es una buena práctica contar un campo específico' *, hecho en el contexto del otro, concretamente * 'No usar 'count (*)'' *, suena como un consejo general para el futuro y como tal es discutible, por decir lo menos. El uso de 'COUNT (*)' para contar filas en un grupo independientemente de los datos en las filas o de cualquier otra condición es perfectamente válido y de acuerdo con el estándar. Tal vez hay algunas implicaciones en MySQL, pero puede que tenga que mencionar que fue así. –

+0

@Andriy - También siempre asumí que 'count (*)' debería evitarse cuando sea posible? Aunque la sintaxis es válida y tal vez no está relacionada con el problema de la operación, sí existe [una diferencia notable en cuanto al rendimiento] (http://www.mysqlperformanceblog.com/2007/04/10/count-vs-countcol/). Sin embargo, no soy DBA, pero como desarrollador siempre he evitado 'count (*)' cuando es posible debido a esto. Puede que haya entendido mal algo aquí, por favor déjame saber si lo hice. – stefgosselin

3

Irónicamente esto parece estar relacionado con optimizaciones; utilizando LIKE fuerza a MySQL a dejar de usar posibles índices (al menos con columnas numéricas, porque tiene que convertirlos todos en cadenas para la comparación).

Así que al usar = parece que MySQL simplemente se queda sin espacio (memoria/disco) para usar el índice (ver configuración key_buffer).

Por supuesto, esto es solo una corazonada y no sé mucho sobre NDB para ayudarlo aún más, pero espero que esto lo lleve en la dirección correcta.