Al ejecutar esta consulta me tarda como 10 segundos sobre una base de
3600 registros, como puedo optimizar esta consulta ?
esta consulta la utilizo para buscar texto que coincida en 2 tablas
contacts y extencions.
@contacts = Contact.find_by_sql [" SELECT contacts.id[id],
contacts.name[name],
contacts.phone[phone],
contacts.address[address],
contacts.email[email],
contacts.category[category],
contacts.user_id[user_id],
contacts.note[note],
extencions.name[ext_name] FROM contacts, extencions where
contacts.user_id
= ?
and
(contacts.name LIKE ?
or
contacts.phone LIKE ?
or
contacts.address LIKE ?
or
contacts.email LIKE ?
or
contacts.category LIKE ?
or
contacts.note LIKE ? or extencions.name LIKE ? and contacts.id =
extencions.contact_id)
GROUP
BY contacts.id ORDER BY contacts.name LIMIT 50
",
session[:user_id], cadena, cadena, cadena, cadena, cadena, cadena,
cadena]
@contacts = Contact.find_all_y_user_id.(session[:user_id],
:joins => [:extensions],
:include => [:extensions],
:conditions => ["contacts.name LIKE ? or contacts.phone LIKE ? or
contacts.address LIKE ? or contacts.email LIKE ? or contacts.category
LIKE ? or contacts.note LIKE ? or extencions.name LIKE ? ", cadena,
cadena, cadena, cadena, cadena, cadena],
:group => “id”,
:order => “name”,
:limit => 50)
y luego puedes hacer @contacts.first.extension.name sin coste, gracias
al include.
Obviamente, la tardanza es un problema de SQL y no de rails.
¿Qué base de datos es?
A simple vista, deberías cerciorarte que el query esté bien … Yo
cerraría el paréntesis antes del and o usaría un inner join…
contacts.note LIKE ? or extencions.name LIKE ? ) and contacts.id =
extencions.contact_id
El día 26 de mayo de 2009 9:32, Silvio Q. [email protected]
escribió:>> contacts.address[address],
contacts.phone LIKE ?
BY contacts.id ORDER BY contacts.name LIMIT 50
contacts.note LIKE ? or extencions.name LIKE ? ) and contacts.id =
extencions.contact_id
Por cierto, si la base de datos va creciendo, tenés que pensar en una
solución “Full text search”, porque no va a haber motor de base de
datos que se banque una cosa
así.Silvio
Al ejecutar esta consulta me tarda como 10 segundos sobre una base de
3600 registros, como puedo optimizar esta consulta ?
Hola,
Es más o menos sabido que las consultas con LIKE en MySQL son lentas
para conjuntos de datos grandes (puedes encontrar multitud de
variantes de esta afirmación en google). No sé si se puede considerar
grande una tabla con 3600 filas, pero en fin, tu problema
ahí está.
Alternativas que tienes:
Como dice Lleir, cambiar LIKE por = donde te sea posible (y viendo
que no utilizas el carácter % como comodín, es posible que puedas
hacerlo en toda la consulta).
Si estás en MySQL y con tablas myisam, puedes usar FULLTEX KEYS. No
es una solución perfecta, sin duda te acopla, y tendrás que hacer
alguna chapucilla ya que Rails no lo soporta directamente, pero
funciona y ahí está mysql full text keys - Google Search
La solución más chula pero también la que más cambios implica
respecto a lo que estás haciendo es usar motores de búsqueda
específicos. Mi experiencia con Sphinx y ThinkingSphinx es bastante
satisfactoria http://www.sphinxsearch.com/ http://freelancing-god.github.com/ts/en/
Espero que estas pistas te sirvan de ayuda, un saludo
Al ejecutar esta consulta me tarda como 10 segundos sobre una base de
3600 registros, como puedo optimizar esta consulta ?
Hola,
Es más o menos sabido que las consultas con LIKE en MySQL son lentas
para conjuntos de datos grandes (puedes encontrar multitud de
variantes de esta afirmación en google)
Me estoy dando cuenta que he asumido que estabas usando MySQL a pesar
de que tú no lo decías, espero que las pistas te sean de igual
utilidad aunque yo haya metido la pata
@contacts = Contact.find_all_y_user_id.(session[:user_id],
:joins => [:extensions],
:include => [:extensions],
:conditions => ["contacts.name LIKE ? or contacts.phone LIKE ? or
contacts.address LIKE ? or contacts.email LIKE ? or contacts.category
LIKE ? or contacts.note LIKE ? or extencions.name LIKE ? ", cadena,
cadena, cadena, cadena, cadena, cadena],
:group => “id”,
:order => “name”,
:limit => 50)
y luego puedes hacer @contacts.first.extension.name sin coste, gracias
al include.
SQLite3::SQLException: ambiguous column name: name: SELECT “contacts”.*
FROM “contacts” INNER JOIN “extencions” ON extencions.contact_id =
contacts.id WHERE (contacts.name LIKE ‘%remis%’ or contacts.phone LIKE
‘%remis%’ or
contacts.address LIKE ‘%remis%’ or contacts.email LIKE ‘%remis%’ or
contacts.category
LIKE ‘%remis%’ or contacts.note LIKE ‘%remis%’ or extencions.name LIKE
‘%remis%’) AND (“contacts”.“user_id” = 1) GROUP BY id ORDER BY name
LIMIT 50
yo calculo que es por que tengo en ambas tablas campos con el nombre
name, en mi consulta yo especifico extencions.name[ext_name] como nombre
alternativo en tu consulta como lo hago ?
se redujo el tiempo de búsqueda ahora es casi inmediato antes tardaba
como 10 segundos
La consulta quedo asi:
@contacts = Contact.find_all_by_user_id(session[:user_id],
:joins => [:extencions],
:include => [:extencions],
:conditions => [“contacts.name LIKE ? or contacts.phone LIKE ? or
contacts.address LIKE ? or contacts.email LIKE ? or contacts.category
LIKE ? or contacts.note LIKE ? or extencions.name LIKE ?”, cadena,
cadena, cadena, cadena, cadena, cadena, cadena],
:group => “contacts.id”,
:order => “contacts.name”,
:limit => 50)
Me estoy dando cuenta que he asumido que estabas usando MySQL a pesar
de que tú no lo decÃas, espero que las pistas te sean de igual
utilidad aunque yo haya metido la pata
conste que no he optimizado nada, lo �nica �s que hacer un inner join
entre dos tablas �s m�s �ptimo la mayoria de casos mientras que el
producto de las dos tablas requiere mas memoria y recursos.
Tienes indices puestos? Y est�n en el orden correcto?
conste que no he optimizado nada, lo única és que hacer un inner join
entre dos tablas és màs óptimo la mayoria de casos mientras que el
producto de las dos tablas requiere mas memoria y recursos.
Tienes indices puestos? Y están en el orden correcto?
asi creo el indice pero como lo uso ? o en la consulta se usa
automaticamente ?
Los indices se usan si estan disponibles y la consulta està bien hecha.
asi creo el indice pero como lo uso ? o en la consulta se usa
automaticamente ?
Los indices se usan si estan disponibles y la consulta està bien hecha.
se usan automaticamente quiero decir
MySql y otros motores de bases de datos tienen un parseador de
sentencias, que intentan mejorar lo que tu escrives, giran el orden de
las condicions, elijen los mejores índices, … A menos que no lo
forces manualmente, si tienes indices bien definidos no te hace falta
decir nada para que actuen correctamente quando los necesites.
Para crear los indices mejor usar migraciones, del tipo
add_index :nombre_tabla, :nombre_campo, …
asi creo el indice pero como lo uso ? o en la consulta se usa
automaticamente ?
Los indices se usan si estan disponibles y la consulta està bien hecha.
se usan automaticamente quiero decir
Encontre un problema en la consulta
solo me devuelve contactos que contengan extensiones
contacts.phone LIKE ? or
contacts.address LIKE ? or contacts.email LIKE ? or
contacts.category
LIKE ? or contacts.note LIKE ? or extencions.name LIKE
?", cadena,
cadena, cadena, cadena, cadena, cadena, cadena],
:group => “contacts.id”,
:order => “contacts.name”,
:limit => 50)
Si lo tubiera que hacer con Sql meteria un left join en vez de un
inner join, pero con rails no he savido hacer-lo nunca, la unica
solucion que te puedo dar, que no es muy bonita pero funciona es
@contacts = Contact.find_all_by_user_id(session[:user_id],
:joins => [“left join extensions on
extensions.contact_id = contacts.id”],
:include => [:extencions],
:conditions => [“contacts.name LIKE ? or
contacts.phone LIKE ? or
contacts.address LIKE ? or contacts.email LIKE ? or
contacts.category
LIKE ? or contacts.note LIKE ? or extencions.name LIKE
?”, cadena,
cadena, cadena, cadena, cadena, cadena, cadena],
:group => “contacts.id”,
:order => “contacts.name”,
:limit => 50)
extencions.contact_id = contacts.id"],
:include => [:extencions],
:conditions => [“contacts.name LIKE ? or
contacts.phone LIKE ? or
contacts.address LIKE ? or contacts.email LIKE ? or
contacts.category
LIKE ? or contacts.note LIKE ? or extencions.name LIKE
?”, cadena,
cadena, cadena, cadena, cadena, cadena, cadena],
:group => “contacts.id”,
:order => “contacts.name”,
:limit => 50)