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 = "S"</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>AND (app.fb_appid=N OR (app.status="S" 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"><<a href="mailto:ramagonzalo@yahoo.com.ar">ramagonzalo@yahoo.com.ar</a>></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 = "S" AND (app.fb_appid=N OR<br>
(app.status="S" 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 = "S" AND (app.fb_appid=N OR<br>
(app.status="S" 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>
> Hola, Gonzalo.<br>
><br>
> El tema de la optimización de la DB no es nada trivial ni simple.<br>
><br>
> Los problemas, como decis, vienen de varios lugares. Algunos<br>
> importantes son: la capacidad del server, la configuración del motor,<br>
> la calidad de las consultas y el buen uso de los indices.<br>
><br>
> Si tenes ganas de meterte con los tres últimos puntos:<br>
><br>
</div>> Para empezar bajate <a href="http://mysqltuner.pl" target="_blank">mysqltuner.pl</a> <<a href="http://mysqltuner.pl" target="_blank">http://mysqltuner.pl</a>>, dale<br>
<div class="im">> permisos y ejecutalo (necesitás el usuario y pass del admin del motor<br>
> mysql). Es un script que analiza tu configuración de mysql y compara<br>
> con las estadísticas del motor para decirte que valores se pueden<br>
> mejorar. Te lo bajas con:<br>
><br>
</div>> wget <a href="http://mysqltuner.pl" target="_blank">mysqltuner.pl</a> <<a href="http://mysqltuner.pl" target="_blank">http://mysqltuner.pl</a>><br>
<div><div></div><div class="h5">><br>
><br>
> Por otro lado, hay consultas que le exigen muchos recursos a la db.<br>
> Por ejemplo, las consultas con ORDER BY RAND() son muy intensivas para<br>
> el motor, por el modo de funcionar de las mismas. Con tablas medio<br>
> chicas (unos 300 registros) en un server no muy importante se nota<br>
> mucho la diferencia.<br>
><br>
> Otra cosa, intentá no usar funciones en el server para hacer las<br>
> comparaciones/ordenamientos. Por ejemplo, haciendo un buscador,<br>
> necesitaba calcular la distancia de Levenstein (un valor que te da la<br>
> diferencia entre dos palabras, sirve para hacer el "Quizás quiso<br>
> decir..."). Probé con una función en el motor, trayendo las 3 palabras<br>
> mas similares y probé trayendo todo el diccionario (unas 3000<br>
> palabras) y calculando la distancia con php. La última opción resultó<br>
> mucho más rápida y menos intensiva para el procesador.<br>
><br>
><br>
> Otro de los problemas que podés tener de rendimiento en las<br>
> consultas (y para mi uno de los más importantes) es el uso de los<br>
> índices. Una consulta que busca un registro en una tabla sin índices<br>
> puede tener que recorrer toda la tabla. Con el ratio de inserciones<br>
> que tenés, calculo que tus tablas no debe ser chicas. Esto es una<br>
> patada al server.<br>
><br>
> Para detectar consultas que no tienen índices podés activar el "mysql<br>
> slow query log" en el archivo de configuración my.cnf.<br>
> Esta es mi config (para la version 5.1.43, para versiones anteriores<br>
> fijate en el manual o en la pagina de mysql porque algunas son distintas):<br>
> log_slow_queries = /usr/local/mysql/data/mysql-slow.log<br>
> long_query_time = 5<br>
> log-queries-not-using-indexes<br>
><br>
> El archivo lo podés analizar con:<br>
> mysqldumpslow -t 10 /usr/local/mysql/data/mysql-slow.log<br>
><br>
> Eso te va a dar las 10 consultas que más tiempo tarden en ejecutarse.<br>
> Buscá otros parámetros en la ayuda del programa, para ver las<br>
> consultas que más se ejecutan, etc.<br>
><br>
> Una vez que tengas la consulta que te interesa, podés usar la<br>
> sentencia EXPLAIN de mysql y ver la salida. Por ejemplo, vamos a tomar<br>
> una consulta:<br>
> SELECT notas.*,usuarios.username FROM notas JOIN usuarios ON<br>
</div></div>> <a href="http://usuarios.id" target="_blank">usuarios.id</a> <<a href="http://usuarios.id" target="_blank">http://usuarios.id</a>>=notas.id_usuario LIMIT 10<br>
<div class="im">> Para analizarla, ejecutaríamos:<br>
> EXPLAIN SELECT notas.*,usuarios.username FROM notas JOIN usuarios ON<br>
</div>> <a href="http://usuarios.id" target="_blank">usuarios.id</a> <<a href="http://usuarios.id" target="_blank">http://usuarios.id</a>>=notas.id_usuario LIMIT 10<br>
<div><div></div><div class="h5">><br>
> El resultado es algo así (en el mail se va a ver feo, miralo por<br>
> pantalla o copialo-pegalo y acomodá las lineas):<br>
> +----+-------------+-------------+--------+---------------+---------+---------+----------------------------------------------+------+-------+<br>
> | id | select_type | table | type | possible_keys | key |<br>
> key_len | ref | rows | Extra |<br>
> +----+-------------+-------------+--------+---------------+---------+---------+----------------------------------------------+------+-------+<br>
> | 1 | SIMPLE | comentarios | ALL | NULL | NULL |<br>
> NULL | NULL | 192 | |<br>
> | 1 | SIMPLE | usuarios | eq_ref | PRIMARY | PRIMARY |<br>
> 4 | hispabodas_hispabodas.comentarios.id_usuario | 1 | |<br>
> +----+-------------+-------------+--------+---------------+---------+---------+----------------------------------------------+------+-------+<br>
> En esta respuesta el server nos dice las tablas que se consultaron, el<br>
> orden en que se consultan, los posibles índices a usar, los que se<br>
> usaron, la referencia del indice a otras tablas, la cantidad de<br>
> registros que se consultaron de la tabla e información extra.<br>
><br>
> Con todos estos datos podés analizar un poco mejor la consulta, saber<br>
> cómo la ve el motor y optimizarla.<br>
><br>
> Como comentario final, acordate que cada índice que agregues a la<br>
> tabla la hace más rápida al consultar, pero más lenta al<br>
> insertar/eliminar/modificar. No te excedas con los índices que no se<br>
> usan porque puede ser contraproducente.<br>
><br>
> Con esto vas a poder optimizar algunas consultas, por lo menos las que<br>
> más consumen. Después de dejar todo 10 puntos, vas a tener que meterte<br>
> con otras opciones, como te decía Leo. El caché es una muy buena<br>
> opción. A mi me bajó el uso del procesador por parte del motor del 80%<br>
> (antes del cache) al 20% (despues del cache).<br>
><br>
> Yo no usaría conexiones persistentes, por todo lo que te dijo Leo.<br>
><br>
> Lo que si deberías hacer es (si usás php-mysql) usar la librería<br>
> mysqli (no la mysql) que está más optimizada para motores nuevos (a<br>
> partir de 5.0).<br>
><br>
> Estoy a punto de escribir algo un poco más detallado sobre esto.<br>
> Cuando tenga tiempo lo haré.<br>
><br>
> Cualquier cosa avisá y reportá resultados.<br>
><br>
> Saludos, Matias.<br>
><br>
><br>
> El 31 de agosto de 2010 18:17, Leonardo Tadei - Pegasus Tech Supply<br>
</div></div>> <<a href="mailto:leonardot@pegasusnet.com.ar">leonardot@pegasusnet.com.ar</a> <mailto:<a href="mailto:leonardot@pegasusnet.com.ar">leonardot@pegasusnet.com.ar</a>>><br>
<div><div></div><div class="h5">> escribió:<br>
><br>
> Hola Gonzalo,<br>
><br>
> El mar, 31-08-2010 a las 06:34 -0300, Rama Gonzalo escribió:<br>
> > Hola, tengo una DB con algo mas de 140 consultas y 10 inserciones<br>
> > aprox. por segundo (usuarios diferentes) y tengo problemas en el<br>
> > rendimientos, desde ya que se puede deber a mil cosas, pero quisiera<br>
> > saber si las conexiones persistentes me pueden ayudar a mejorar<br>
> un poco<br>
> > o complicaría más la cosa.<br>
> > Y en que casos en conveniente y en cuales no.<br>
><br>
> Casi nunca convienen las conexiones persistentes, y sobre<br>
> todo, no son<br>
> aplicables cuando los usuarios de la DB son distintos.<br>
> Si implementás conexiones persistentes, tenés que tener<br>
> mucho, pero<br>
> mucho cuidado de cerrarlas correctamente, porque si no se te cae el<br>
> server por demasiadas conexiones abiertas.<br>
><br>
> Para este caso, tal vez te convenga más implementar un<br>
> sistema de<br>
> caché, para que las 140 consultas bajen a la misma cantidad que<br>
> tenés de<br>
> inserciones.<br>
><br>
> Después, el paso que sigue son tablas en RAM, y bajarlas a<br>
> disco cada<br>
> tanto, y de ahí pasás a clusterizar el almacenamiento o pasarte a<br>
> DB no<br>
> relacionales, que según dicen pero yo no probé, tienen muy buen<br>
> rendimiento bajo estos escenarios, aunque en el camino perdés la<br>
> consistencia automática de los almacenamientos.<br>
><br>
> > Muchas gracias.<br>
><br>
> Por nada!<br>
><br>
> --<br>
><br>
> Leonardo Tadei<br>
</div></div>> <a href="mailto:leonardot@pegasusnet.com.ar">leonardot@pegasusnet.com.ar</a> <mailto:<a href="mailto:leonardot@pegasusnet.com.ar">leonardot@pegasusnet.com.ar</a>><br>
<div class="im">> <a href="http://blog.pegasusnet.com.ar" target="_blank">http://blog.pegasusnet.com.ar</a><br>
> 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>
><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>
</div>> <mailto:<a href="mailto:Php-avanzado@pato2.fi.mdp.edu.ar">Php-avanzado@pato2.fi.mdp.edu.ar</a>><br>
<div class="im">> <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>
><br>
><br>
> --<br>
> Matias Fernando Gea<br>
</div>> <a href="mailto:matigea@gmail.com">matigea@gmail.com</a> <mailto:<a href="mailto:matigea@gmail.com">matigea@gmail.com</a>><br>
<div class="im">> <a href="http://www.mfgea.com.ar" target="_blank">http://www.mfgea.com.ar</a><br>
><br>
><br>
</div><div><div></div><div class="h5">> _______________________________________________<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>
<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>