Forum: Rails-ES find_by_sql muy lento

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Oscar D. (Guest)
on 2009-05-26 15:21
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]
LLeïr Borràs (Guest)
on 2009-05-26 16:00
(Received via mailing list)
@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.


2009/5/26 Oscar D. <removed_email_address@domain.invalid>:
LLeïr Borràs (Guest)
on 2009-05-26 16:02
(Received via mailing list)
Pror cierto, y pensando un poco mas, si "cadena" no tinen
ningúncaracter tipo '%' mejor pon '=' donde pones 'like'


2009/5/26 LLeïr Borràs <removed_email_address@domain.invalid>:
Silvio Q. (Guest)
on 2009-05-26 16:33
(Received via mailing list)
El día 26 de mayo de 2009 8:21, Oscar D.
<removed_email_address@domain.invalid>
escribió:>                                                                 
contacts.email[email],
>                                                                 or
>                                                                 ",
> session[:user_id], cadena, cadena, cadena, cadena, cadena, cadena,
> cadena]

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

Silvio
Silvio Q. (Guest)
on 2009-05-26 16:35
(Received via mailing list)
El día 26 de mayo de 2009 9:32, Silvio Q. <removed_email_address@domain.invalid>
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
Sergio Gil Pérez de la Manga (Guest)
on 2009-05-26 16:37
(Received via mailing list)
On 5/26/09, Oscar D. <removed_email_address@domain.invalid> wrote:
> 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:

1. 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).

2. 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á http://www.google.es/search?q=mysql+full+text+keys

3. 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

--
Sergio Gil Pérez de la Manga
e-mail > removed_email_address@domain.invalid
blog > http://www.lacoctelera.com/porras
now > http://twitter.com/porras
Sergio Gil Pérez de la Manga (Guest)
on 2009-05-26 16:40
(Received via mailing list)
On 5/26/09, Sergio Gil Pérez de la Manga <removed_email_address@domain.invalid> 
wrote:
> On 5/26/09, Oscar D. <removed_email_address@domain.invalid> wrote:
>> 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 ;-)

--
Sergio Gil Pérez de la Manga
e-mail > removed_email_address@domain.invalid
blog > http://www.lacoctelera.com/porras
now > http://twitter.com/porras
Manuel González Noriega (Guest)
on 2009-05-26 16:46
(Received via mailing list)
2009/5/26 Sergio Gil Pérez de la Manga <removed_email_address@domain.invalid>

>
>
> 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 ;-)
>
>
Mira que eres melón, Sergio
Oscar D. (Guest)
on 2009-05-26 16:49
LLeïr Borràs wrote:
> @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.
>
>
> 2009/5/26 Oscar D. <removed_email_address@domain.invalid>:

Gracias por tu respuesta

Me tira el siguiente error

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 ?

Utilizo Sqlite3
LLeïr Borràs (Guest)
on 2009-05-26 16:56
(Received via mailing list)
es por el order by, pon :order => "contacts.name"

2009/5/26 Oscar D. <removed_email_address@domain.invalid>:
Oscar D. (Guest)
on 2009-05-26 17:05
LLeïr Borràs wrote:
> es por el order by, pon :order => "contacts.name"
>
> 2009/5/26 Oscar D. <removed_email_address@domain.invalid>:

Muchas Gracias a todos, funciono perfecto !!!!!

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)

Saludos a todos !!!!
LLeïr Borràs (Guest)
on 2009-05-26 17:11
(Received via mailing list)
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?


2009/5/26 Oscar D. <removed_email_address@domain.invalid>:
Oscar D. (Guest)
on 2009-05-26 17:18
LLeïr Borràs wrote:
> 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?
>
>
> 2009/5/26 Oscar D. <removed_email_address@domain.invalid>:


Estuve leyendo documentación sobre los indices, pero no me quedo muy
claro

asi creo el indice pero como lo uso ? o en la consulta se usa
automaticamente ?

en la tabla contacts

CREATE INDEX mi_indice ON  (name, phone)
Dani D. (Guest)
on 2009-05-26 17:28
(Received via mailing list)
2009/5/26 Oscar D. <removed_email_address@domain.invalid>:
> 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.
Dani D. (Guest)
on 2009-05-26 17:29
(Received via mailing list)
2009/5/26 Dani D. <removed_email_address@domain.invalid>:
> 2009/5/26 Oscar D. <removed_email_address@domain.invalid>:
>> 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
LLeïr Borràs (Guest)
on 2009-05-26 17:40
(Received via mailing list)
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, ....

2009/5/26 Dani D. <removed_email_address@domain.invalid>:
Oscar D. (Guest)
on 2009-05-26 17:46
Dani D. wrote:
> 2009/5/26 Dani D. <removed_email_address@domain.invalid>:
>> 2009/5/26 Oscar D. <removed_email_address@domain.invalid>:
>>> 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

como hago para ver los contactos que no tienen extensiones también ?

es una consulta sobre una agenda la cual algunos contactos tiene
extensiones y otros no.


      cadena = "%" + params[:name] + "%"

      @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)
LLeïr Borràs (Guest)
on 2009-05-26 18:03
(Received via mailing list)
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)


2009/5/26 Oscar D. <removed_email_address@domain.invalid>:
Sergio Gil Pérez de la Manga (Guest)
on 2009-05-26 18:09
(Received via mailing list)
On 5/26/09, Manuel González Noriega <removed_email_address@domain.invalid>
wrote:
>
Ay, ya me estaba pensando que ya no me querías, qué emoción, se me cae
la lagrimita :_)

--
Sergio Gil Pérez de la Manga
e-mail > removed_email_address@domain.invalid
blog > http://www.lacoctelera.com/porras
now > http://twitter.com/porras
Oscar D. (Guest)
on 2009-05-26 18:51
Sergio Gil Pérez de la Manga wrote:
> On 5/26/09, Manuel Gonz�lez Noriega <removed_email_address@domain.invalid>
> wrote:
>>
> Ay, ya me estaba pensando que ya no me quer�as, qu� emoci�n, se me cae
> la lagrimita :_)
>
> --
> Sergio Gil P�rez de la Manga
> e-mail > removed_email_address@domain.invalid
> blog > http://www.lacoctelera.com/porras
> now > http://twitter.com/porras

Ahora si !!! funciona perfecto

lo que no entiendo es por que decís que no es muy bonita que problemas
puede traer ?

      cadena = "%" + params[:name] + "%"

      @contacts = Contact.find_all_by_user_id(session[:user_id],
                  :joins => ["left join extencions on
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)
LLeïr Borràs (Guest)
on 2009-05-26 19:25
(Received via mailing list)
tiene problemas de acoblamiento, cuando metes codigo sql en una
consulta de un modelo augmentas las posibilidades de que un cambio de
base de datos de joda la aplicación

2009/5/26 Oscar D. <removed_email_address@domain.invalid>:
Oscar D. (Guest)
on 2009-05-26 19:39
LLeïr Borràs wrote:
> tiene problemas de acoblamiento, cuando metes codigo sql en una
> consulta de un modelo augmentas las posibilidades de que un cambio de
> base de datos de joda la aplicación
>
> 2009/5/26 Oscar D. <removed_email_address@domain.invalid>:

Ok Gracias por tu ayuda me fue de mucha utilidad.

Saludos !!!
Emili P. (Guest)
on 2009-05-27 10:05
(Received via mailing list)
> Tienes indices puestos? Y están en el orden correcto?

Por lo visto usa SQLite, si es así no dispone de indices :(


--
Daniel R. Troitiño (Guest)
on 2009-05-27 10:14
(Received via mailing list)
On Wed, May 27, 2009 at 08:05, Emili Parreño 
<removed_email_address@domain.invalid> wrote:
>> Tienes indices puestos? Y están en el orden correcto?
>
> Por lo visto usa SQLite, si es así no dispone de indices :(
>

¿Perdón? ¿Qué SQLite no dispone de indices?

Creando índices en SQLite: <http://sqlite.org/lang_createindex.html>
Algunas formas en las SQLite utiliza los índices:
<http://sqlite.org/optoverview.html>

Lo siento, pero tenía que defender al pequeñín. Me cae demasiado bien
y es tan mono. Yo no puedo vivir sin SQLite.
Emili P. (Guest)
on 2009-05-27 10:21
(Received via mailing list)
Perdon tienes razon, lo que no permite es especificar la longitud de
los indices, es que ahora estoy con esto liado y me he confundido. I'm
sorry.

No pretendía desmerecer al pequeñín :)

2009/5/27 Daniel R. Troitiño <removed_email_address@domain.invalid>:
> <http://sqlite.org/optoverview.html>
>
> Lo siento, pero tenía que defender al pequeñín. Me cae demasiado bien
> y es tan mono. Yo no puedo vivir sin SQLite.
> _______________________________________________
> Ror-es mailing list
> removed_email_address@domain.invalid
> http://lists.simplelogica.net/mailman/listinfo/ror-es
>



--
This topic is locked and can not be replied to.