Hola, Gonzalo.<div><br></div><div>Esta es una opcion para que el motor no ejecute dos búsquedas. La técnica es marcar con un flag los registros que quieras y despues ordenar por ese flag (en este caso, el flag está invertido, a los idiomas que selecciona el usuario se le asigna un cero y al resto un uno).</div>
<div>Hay que ver cómo rinde con el tema de los índices, porque al generar el flag al vuelo el motor debe usar una tabla temporal para ordenar.</div><div><br></div><div><div>SELECT <a href="http://text.id">text.id</a>,text.text, IF(app.lang_id IN(N,N,N,N,N),0,1) AS orden</div>
<div>FROM app,text</div><div>WHERE text.app_id=<a href="http://app.id">app.id</a></div><div><span class="Apple-tab-span" style="white-space:pre">        </span>AND text.status = &quot;S&quot;</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>AND (app.fb_appid=N OR (app.status=&quot;S&quot; AND app.deleted=N))</div>
<div>ORDER BY orden,text.created DESC</div><div>LIMIT N,N</div><div><br></div>Probala y avisá.</div><div><br></div><div>Saludos!</div><div><br></div><div><br><div class="gmail_quote">El 10 de septiembre de 2010 01:57, Rama Gonzalo <span dir="ltr">&lt;<a href="mailto:ramagonzalo@yahoo.com.ar">ramagonzalo@yahoo.com.ar</a>&gt;</span> escribió:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">  La verdad. que me acabo de dar cuenta.. muchas animalas.. muy buenas<br>
estas hermientas.. aun estoy en los primeros pasos de optimización, pero<br>
bueno.. ejemplo.. teníamos una consulta que demoraba casi 120<br>
segundos..(si si.. ) con poner solo un índice paso a 2 segundos.. ahora<br>
es solo una animaladita :).<br>
<br>
------- analizando el log con mysqldumpslow, entre una de las primeras<br>
aparece esta ----------------<br>
Count: 36  Time=0.56s (20s)  Lock=0.00s (0s)  Rows=15.0 (540),<br>
   (<br>
   SELECT <a href="http://text.id" target="_blank">text.id</a>,text.text FROM app,text WHERE<br>
   text.app_id=<a href="http://app.id" target="_blank">app.id</a> AND text.status = &quot;S&quot; AND (app.fb_appid=N OR<br>
(app.status=&quot;S&quot; AND app.deleted=N)) AND app.lang_id IN(N,N,N,N,N) ORDER<br>
BY text.created DESC LIMIT N)<br>
   UNION<br>
   (<br>
   SELECT <a href="http://text.id" target="_blank">text.id</a>,text.text FROM app,text WHERE<br>
   text.app_id=<a href="http://app.id" target="_blank">app.id</a> AND text.status = &quot;S&quot; AND (app.fb_appid=N OR<br>
(app.status=&quot;S&quot; AND app.deleted=N)) AND app.lang_id NOT IN(N,N,N,N,N)<br>
ORDER BY text.created DESC LIMIT N)<br>
   LIMIT N,N<br>
--------------------------------------------<br>
Según mi análisis esta demorando casi 1 segundo, así tengo varias.<br>
Lo que quisiera preguntarles es ¿cómo se podría mejorar la consulta?.<br>
Tengo un listado de textos en varios idiomas,dialectos, y necesito<br>
listar primero todos los de habla hispana(o el que fuese solicitado por<br>
el user) es_ES, es_LA, es_CO , etc y luego el resto.. por lo tanto lo<br>
primero que se nos ocurrío fue hacer un UNION  tomando sólo los de ese<br>
idioma y luegos todos menos los de ese idioma.., desde un  comienzo lo<br>
ví medio vestía, pero no me dieron para más los conocimientos si lo<br>
quería hacer todo en una misma consulta SQL sin mechar con PHP.<br>
<br>
¿Qué alternativas tengo en esta consulta?<br>
<br>
<br>
Mil gracias.. muy buenos ambos aportes.<br>
<div class="im"><br>
<br>
<br>
&gt; Hola, Gonzalo.<br>
&gt;<br>
&gt; El tema de la optimización de la DB no es nada trivial ni simple.<br>
&gt;<br>
&gt; Los problemas, como decis, vienen de varios lugares. Algunos<br>
&gt; importantes son: la capacidad del server, la configuración del motor,<br>
&gt; la calidad de las consultas y el buen uso de los indices.<br>
&gt;<br>
&gt; Si tenes ganas de meterte con los tres últimos puntos:<br>
&gt;<br>
</div>&gt; Para empezar bajate <a href="http://mysqltuner.pl" target="_blank">mysqltuner.pl</a> &lt;<a href="http://mysqltuner.pl" target="_blank">http://mysqltuner.pl</a>&gt;, dale<br>
<div class="im">&gt; permisos y ejecutalo (necesitás el usuario y pass del admin del motor<br>
&gt; mysql). Es un script que analiza tu configuración de mysql y compara<br>
&gt; con las estadísticas del motor para decirte que valores se pueden<br>
&gt; mejorar. Te lo bajas con:<br>
&gt;<br>
</div>&gt; wget <a href="http://mysqltuner.pl" target="_blank">mysqltuner.pl</a> &lt;<a href="http://mysqltuner.pl" target="_blank">http://mysqltuner.pl</a>&gt;<br>
<div><div></div><div class="h5">&gt;<br>
&gt;<br>
&gt; Por otro lado, hay consultas que le exigen muchos recursos a la db.<br>
&gt; Por ejemplo, las consultas con ORDER BY RAND() son muy intensivas para<br>
&gt; el motor, por el modo de funcionar de las mismas. Con tablas medio<br>
&gt; chicas (unos 300 registros) en un server no muy importante se nota<br>
&gt; mucho la diferencia.<br>
&gt;<br>
&gt; Otra cosa, intentá no usar funciones en el server para hacer las<br>
&gt; comparaciones/ordenamientos. Por ejemplo, haciendo un buscador,<br>
&gt; necesitaba calcular la distancia de Levenstein (un valor que te da la<br>
&gt; diferencia entre dos palabras, sirve para hacer el &quot;Quizás quiso<br>
&gt; decir...&quot;). Probé con una función en el motor, trayendo las 3 palabras<br>
&gt; mas similares y probé trayendo todo el diccionario (unas 3000<br>
&gt; palabras) y calculando la distancia con php. La última opción resultó<br>
&gt; mucho más rápida y menos intensiva para el procesador.<br>
&gt;<br>
&gt;<br>
&gt; Otro de los problemas que podés tener de rendimiento en las<br>
&gt; consultas (y para mi uno de los más importantes) es el uso de los<br>
&gt; índices. Una consulta que busca un registro en una tabla sin índices<br>
&gt; puede tener que recorrer toda la tabla. Con el ratio de inserciones<br>
&gt; que tenés, calculo que tus tablas no debe ser chicas. Esto es una<br>
&gt; patada al server.<br>
&gt;<br>
&gt; Para detectar consultas que no tienen índices podés activar el &quot;mysql<br>
&gt; slow query log&quot; en el archivo de configuración my.cnf.<br>
&gt; Esta es mi config (para la version 5.1.43, para versiones anteriores<br>
&gt; fijate en el manual o en la pagina de mysql porque algunas son distintas):<br>
&gt; log_slow_queries = /usr/local/mysql/data/mysql-slow.log<br>
&gt; long_query_time = 5<br>
&gt; log-queries-not-using-indexes<br>
&gt;<br>
&gt; El archivo lo podés analizar con:<br>
&gt; mysqldumpslow -t 10 /usr/local/mysql/data/mysql-slow.log<br>
&gt;<br>
&gt; Eso te va a dar las 10 consultas que más tiempo tarden en ejecutarse.<br>
&gt; Buscá otros parámetros en la ayuda del programa, para ver las<br>
&gt; consultas que más se ejecutan, etc.<br>
&gt;<br>
&gt; Una vez que tengas la consulta que te interesa, podés usar la<br>
&gt; sentencia EXPLAIN de mysql y ver la salida. Por ejemplo, vamos a tomar<br>
&gt; una consulta:<br>
&gt; SELECT notas.*,usuarios.username FROM notas JOIN usuarios ON<br>
</div></div>&gt; <a href="http://usuarios.id" target="_blank">usuarios.id</a> &lt;<a href="http://usuarios.id" target="_blank">http://usuarios.id</a>&gt;=notas.id_usuario LIMIT 10<br>
<div class="im">&gt; Para analizarla, ejecutaríamos:<br>
&gt; EXPLAIN SELECT notas.*,usuarios.username FROM notas JOIN usuarios ON<br>
</div>&gt; <a href="http://usuarios.id" target="_blank">usuarios.id</a> &lt;<a href="http://usuarios.id" target="_blank">http://usuarios.id</a>&gt;=notas.id_usuario LIMIT 10<br>
<div><div></div><div class="h5">&gt;<br>
&gt; El resultado es algo así (en el mail se va a ver feo, miralo por<br>
&gt; pantalla o copialo-pegalo y acomodá las lineas):<br>
&gt; +----+-------------+-------------+--------+---------------+---------+---------+----------------------------------------------+------+-------+<br>
&gt; | id | select_type | table       | type   | possible_keys | key     |<br>
&gt; key_len | ref                                          | rows | Extra |<br>
&gt; +----+-------------+-------------+--------+---------------+---------+---------+----------------------------------------------+------+-------+<br>
&gt; |  1 | SIMPLE      | comentarios | ALL    | NULL          | NULL    |<br>
&gt; NULL    | NULL                                         |  192 |       |<br>
&gt; |  1 | SIMPLE      | usuarios    | eq_ref | PRIMARY       | PRIMARY |<br>
&gt; 4       | hispabodas_hispabodas.comentarios.id_usuario |    1 |       |<br>
&gt; +----+-------------+-------------+--------+---------------+---------+---------+----------------------------------------------+------+-------+<br>
&gt; En esta respuesta el server nos dice las tablas que se consultaron, el<br>
&gt; orden en que se consultan, los posibles índices a usar, los que se<br>
&gt; usaron, la referencia del indice a otras tablas, la cantidad de<br>
&gt; registros que se consultaron de la tabla e información extra.<br>
&gt;<br>
&gt; Con todos estos datos podés analizar un poco mejor la consulta, saber<br>
&gt; cómo la ve el motor y optimizarla.<br>
&gt;<br>
&gt; Como comentario final, acordate que cada índice que agregues a la<br>
&gt; tabla la hace más rápida al consultar, pero más lenta al<br>
&gt; insertar/eliminar/modificar. No te excedas con los índices que no se<br>
&gt; usan porque puede ser contraproducente.<br>
&gt;<br>
&gt; Con esto vas a poder optimizar algunas consultas, por lo menos las que<br>
&gt; más consumen. Después de dejar todo 10 puntos, vas a tener que meterte<br>
&gt; con otras opciones, como te decía Leo. El caché es una muy buena<br>
&gt; opción. A mi me bajó el uso del procesador por parte del motor del 80%<br>
&gt; (antes del cache) al 20% (despues del cache).<br>
&gt;<br>
&gt; Yo no usaría conexiones persistentes, por todo lo que te dijo Leo.<br>
&gt;<br>
&gt; Lo que si deberías hacer es (si usás php-mysql) usar la librería<br>
&gt; mysqli (no la mysql) que está más optimizada para motores nuevos (a<br>
&gt; partir de 5.0).<br>
&gt;<br>
&gt; Estoy a punto de escribir algo un poco más detallado sobre esto.<br>
&gt; Cuando tenga tiempo lo haré.<br>
&gt;<br>
&gt; Cualquier cosa avisá y reportá resultados.<br>
&gt;<br>
&gt; Saludos, Matias.<br>
&gt;<br>
&gt;<br>
&gt; El 31 de agosto de 2010 18:17, Leonardo Tadei - Pegasus Tech Supply<br>
</div></div>&gt; &lt;<a href="mailto:leonardot@pegasusnet.com.ar">leonardot@pegasusnet.com.ar</a> &lt;mailto:<a href="mailto:leonardot@pegasusnet.com.ar">leonardot@pegasusnet.com.ar</a>&gt;&gt;<br>
<div><div></div><div class="h5">&gt; escribió:<br>
&gt;<br>
&gt;     Hola Gonzalo,<br>
&gt;<br>
&gt;     El mar, 31-08-2010 a las 06:34 -0300, Rama Gonzalo escribió:<br>
&gt;     &gt; Hola, tengo una DB con algo mas de 140 consultas y 10 inserciones<br>
&gt;     &gt; aprox. por segundo (usuarios diferentes) y tengo problemas en el<br>
&gt;     &gt; rendimientos, desde ya que se puede deber a mil cosas, pero quisiera<br>
&gt;     &gt; saber si las conexiones persistentes me pueden ayudar a mejorar<br>
&gt;     un poco<br>
&gt;     &gt; o complicaría más la cosa.<br>
&gt;     &gt; Y en que casos en conveniente y en cuales no.<br>
&gt;<br>
&gt;            Casi nunca convienen las conexiones persistentes, y sobre<br>
&gt;     todo, no son<br>
&gt;     aplicables cuando los usuarios de la DB son distintos.<br>
&gt;            Si implementás conexiones persistentes, tenés que tener<br>
&gt;     mucho, pero<br>
&gt;     mucho cuidado de cerrarlas correctamente, porque si no se te cae el<br>
&gt;     server por demasiadas conexiones abiertas.<br>
&gt;<br>
&gt;            Para este caso, tal vez te convenga más implementar un<br>
&gt;     sistema de<br>
&gt;     caché, para que las 140 consultas bajen a la misma cantidad que<br>
&gt;     tenés de<br>
&gt;     inserciones.<br>
&gt;<br>
&gt;            Después, el paso que sigue son tablas en RAM, y bajarlas a<br>
&gt;     disco cada<br>
&gt;     tanto, y de ahí pasás a clusterizar el almacenamiento o pasarte a<br>
&gt;     DB no<br>
&gt;     relacionales, que según dicen pero yo no probé, tienen muy buen<br>
&gt;     rendimiento bajo estos escenarios, aunque en el camino perdés la<br>
&gt;     consistencia automática de los almacenamientos.<br>
&gt;<br>
&gt;     &gt; Muchas gracias.<br>
&gt;<br>
&gt;            Por nada!<br>
&gt;<br>
&gt;     --<br>
&gt;<br>
&gt;     Leonardo Tadei<br>
</div></div>&gt;     <a href="mailto:leonardot@pegasusnet.com.ar">leonardot@pegasusnet.com.ar</a> &lt;mailto:<a href="mailto:leonardot@pegasusnet.com.ar">leonardot@pegasusnet.com.ar</a>&gt;<br>
<div class="im">&gt;     <a href="http://blog.pegasusnet.com.ar" target="_blank">http://blog.pegasusnet.com.ar</a><br>
&gt;     Firma pública: <a href="http://www.pegasusnet.com.ar/LeonardoTadei-public.key" target="_blank">http://www.pegasusnet.com.ar/LeonardoTadei-public.key</a><br>
&gt;<br>
&gt;     _______________________________________________<br>
&gt;     Php-avanzado mailing list<br>
&gt;     <a href="mailto:Php-avanzado@pato2.fi.mdp.edu.ar">Php-avanzado@pato2.fi.mdp.edu.ar</a><br>
</div>&gt;     &lt;mailto:<a href="mailto:Php-avanzado@pato2.fi.mdp.edu.ar">Php-avanzado@pato2.fi.mdp.edu.ar</a>&gt;<br>
<div class="im">&gt;     <a href="http://www3.fi.mdp.edu.ar/cgi-bin/mailman/listinfo/php-avanzado" target="_blank">http://www3.fi.mdp.edu.ar/cgi-bin/mailman/listinfo/php-avanzado</a><br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt; --<br>
&gt; Matias Fernando Gea<br>
</div>&gt; <a href="mailto:matigea@gmail.com">matigea@gmail.com</a> &lt;mailto:<a href="mailto:matigea@gmail.com">matigea@gmail.com</a>&gt;<br>
<div class="im">&gt; <a href="http://www.mfgea.com.ar" target="_blank">http://www.mfgea.com.ar</a><br>
&gt;<br>
&gt;<br>
</div><div><div></div><div class="h5">&gt; _______________________________________________<br>
&gt; Php-avanzado mailing list<br>
&gt; <a href="mailto:Php-avanzado@pato2.fi.mdp.edu.ar">Php-avanzado@pato2.fi.mdp.edu.ar</a><br>
&gt; <a href="http://www3.fi.mdp.edu.ar/cgi-bin/mailman/listinfo/php-avanzado" target="_blank">http://www3.fi.mdp.edu.ar/cgi-bin/mailman/listinfo/php-avanzado</a><br>
<br>
_______________________________________________<br>
Php-avanzado mailing list<br>
<a href="mailto:Php-avanzado@pato2.fi.mdp.edu.ar">Php-avanzado@pato2.fi.mdp.edu.ar</a><br>
<a href="http://www3.fi.mdp.edu.ar/cgi-bin/mailman/listinfo/php-avanzado" target="_blank">http://www3.fi.mdp.edu.ar/cgi-bin/mailman/listinfo/php-avanzado</a><br>
</div></div></blockquote></div><br><br clear="all"><br>-- <br>Matias Fernando Gea<br><a href="mailto:matigea@gmail.com">matigea@gmail.com</a><br><a href="http://www.mfgea.com.ar">http://www.mfgea.com.ar</a><br>
</div>