sql >> Base de Datos >  >> RDS >> Mysql

¿Cómo optimizar la consulta si la tabla contiene 10000 entradas usando MySQL?

Intentaría simplificar esto COMPLETAMENTE poniendo disparadores en sus otras tablas y simplemente agregando algunas columnas a su tabla User_Fans... Una para cada conteo respectivo () que está tratando de obtener... de Publicaciones, PostLikes, PostComments, Publicar comentarioMe gusta.

Cuando se agrega un registro a cualquier tabla, simplemente actualice su tabla user_fans para agregar 1 al conteo... de todos modos, será prácticamente instantáneo según la ID de clave del usuario. En cuanto a los "ME GUSTA"... Similar, solo bajo la condición de que algo se active como un "Me gusta", agregue 1. Entonces su consulta será matemática directa en el registro único y no dependerá de CUALQUIER combinación para calcular un valor total "ponderado". A medida que su tabla se vuelve aún más grande, las consultas también se alargarán, ya que tienen más datos para verter y agregar. Está revisando CADA registro de usuario_fan que, en esencia, está consultando cada registro de todas las demás tablas.

Dicho todo esto, manteniendo las tablas como las tienes, las reestructuraría de la siguiente manera...

SELECT 
      uf.user_name,
      uf.user_id,
      @pc := coalesce( PostSummary.PostCount, 000000 ) as PostCount,
      @pl := coalesce( PostLikes.LikesCount, 000000 ) as PostLikes,
      @cc := coalesce( CommentSummary.CommentsCount, 000000 ) as PostComments,
      @cl := coalesce( CommentLikes.LikesCount, 000000 ) as CommentLikes,
      @pc + @cc AS sum_post,
      @pl + @cl AS sum_like, 
      @pCalc := (@pc + @cc) * 10 AS post_cal,
      @lCalc := (@pl + @cl) * 5 AS like_cal,
      @pCalc + @lCalc AS `total`
   FROM
      ( select @pc := 0,
               @pl := 0,
               @cc := 0,
               @cl := 0,
               @pCalc := 0
               @lCalc := 0 ) sqlvars,
      user_fans uf
        LEFT JOIN ( select user_id, COUNT(*) as PostCount
                       from post
                       group by user_id ) as PostSummary
           ON uf.user_id = PostSummary.User_ID

        LEFT JOIN ( select user_id, COUNT(*) as LikesCount
                       from post_likes
                       group by user_id ) as PostLikes
           ON uf.user_id = PostLikes.User_ID

        LEFT JOIN ( select user_id, COUNT(*) as CommentsCount
                       from post_comment
                       group by user_id ) as CommentSummary
           ON uf.user_id = CommentSummary.User_ID

        LEFT JOIN ( select user_id, COUNT(*) as LikesCount
                       from post_comment_likes
                       group by user_id ) as CommentLikes
           ON uf.user_id = CommentLikes.User_ID

   ORDER BY 
      `total` DESC 
   LIMIT 20

My variables are abbreviated as 
"@pc" = PostCount
"@pl" = PostLikes
"@cc" = CommentCount
"@cl" = CommentLike
"@pCalc" = weighted calc of post and comment count * 10 weighted value
"@lCalc" = weighted calc of post and comment likes * 5 weighted value

La UNIÓN IZQUIERDA a las consultas previas ejecuta esas consultas UNA VEZ, luego todo se une en lugar de ser una subconsulta para cada registro. Al usar COALESCE(), si no hay tales entradas en los resultados de la tabla LEFT JOINed, no obtendrá valores NULL que estropeen los cálculos, por lo que los he predeterminado en 000000.

ACLARACIÓN DE SUS PREGUNTAS

Puede tener cualquier CONSULTA como "AS AliasResult". El "As" también se puede usar para simplificar cualquier nombre de tabla largo para facilitar la lectura. Los alias también pueden usar la misma tabla pero como un alias diferente para obtener contenido similar, pero con un propósito diferente.

select
      MyAlias.SomeField
   from
      MySuperLongTableNameInDatabase MyAlias ...

select
      c.LastName,
      o.OrderAmount
   from
      customers c
         join orders o
            on c.customerID = o.customerID  ...

select
      PQ.SomeKey
   from
      ( select ST.SomeKey
           from SomeTable ST
           where ST.SomeDate between X and Y ) as PQ
         JOIN SomeOtherTable SOT
            on PQ.SomeKey = SOT.SomeKey ...

Ahora, la tercera consulta anterior no es práctica y requiere la (consulta completa que da como resultado el alias "PQ" que representa "PreQuery"). Esto se puede hacer si desea limitar previamente un determinado conjunto de otras condiciones complejas y desea un conjunto más pequeño ANTES de realizar uniones adicionales a muchas otras tablas para todos los resultados finales.

Dado que "FROM" no TIENE que ser una tabla real, sino que puede ser una consulta en sí misma, en cualquier otro lugar que se use en la consulta, debe saber cómo hacer referencia a este conjunto de resultados de preconsulta.

Además, cuando se consultan campos, también pueden ser "As FinalColumnName" para simplificar los resultados dondequiera que se utilicen.

seleccione CONCAT (Usuario.Saludo, Usuario.Apellido) como Nombre de cortesía de ...

selectOrder.NonTaxable+ Order.Taxable+ ( Order.Taxable * Order.SalesTaxRate ) as OrderTotalWithTaxfrom ...

NO se requiere que el nombre de columna "As" sea un agregado, pero se ve más comúnmente de esa manera.

Ahora, con respecto a las variables de MySQL... Si estuviera realizando un procedimiento almacenado, muchas personas las declararán previamente configurando sus valores predeterminados antes del resto del procedimiento. Puede hacerlo en línea en una consulta simplemente configurando y dando a ese resultado una referencia de "Alias". Al hacer estas variables, la selección simulará siempre devolver un valor de REGISTRO ÚNICO de los valores. Es casi como un registro único actualizable utilizado dentro de la consulta. No necesita aplicar ninguna condición específica de "Unir", ya que puede no tener ninguna relación con el resto de las tablas en una consulta... En esencia, crea un resultado cartesiano, pero un registro contra cualquier otra tabla nunca creará duplica de todos modos, por lo que no hay daños aguas abajo.

select 
       ...
   from 
      ( select @SomeVar := 0,
               @SomeDate := curdate(),
               @SomeString := "hello" ) as SQLVars

Ahora, cómo funcionan los sqlvars. Piense en un programa lineal... Un comando se ejecuta en la secuencia exacta a medida que se ejecuta la consulta. Luego, ese valor se vuelve a almacenar en el registro "SQLVars" listo para la próxima vez. Sin embargo, no lo hace referencia como SQLVars.SomeVar o SQLVars.SomeDate... solo @SomeVar :=someNewValue. Ahora, cuando @var se usa en una consulta, también se almacena como "Como nombre de columna" en el conjunto de resultados. Algunas veces, esto puede ser solo un valor calculado de marcador de posición en la preparación del siguiente registro. Cada valor está entonces directamente disponible para la siguiente fila. Entonces, dada la siguiente muestra...

select
      @SomeVar := SomeVar * 2 as FirstVal,
      @SomeVar := SomeVar * 2 as SecondVal,
      @SomeVar := SomeVar * 2 as ThirdVal
   from
      ( select @SomeVar := 1 ) sqlvars,
      AnotherTable
   limit 3

Will result in 3 records with the values of 

FirstVal    SecondVal   ThirdVal
2           4           8
16          32          64
128         256         512

Observe cómo se usa el valor de @SomeVar a medida que lo usa cada columna... Entonces, incluso en el mismo registro, el valor actualizado está disponible de inmediato para la siguiente columna... Dicho esto, ahora trate de construir un recuento de registros simulado / ranking por cada cliente...

select
      o.CustomerID,
      o.OrderID
      @SeqNo := if( @LastID = o.CustomerID, @SeqNo +1, 1 ) as CustomerSequence,
      @LastID := o.CustomerID as PlaceHolderToSaveForNextRecordCompare
   from
      orders o,
      ( select @SeqNo := 0, @LastID := 0 ) sqlvars
   order by
      o.CustomerID

La cláusula "Ordenar por" obliga a que los resultados se devuelvan primero en secuencia. Entonces, aquí se devuelven los registros por cliente. La primera vez, LastID es 0 y el ID del cliente es, digamos... 5. Dado que es diferente, devuelve 1 como @SeqNo, ENTONCES conserva esa ID de cliente en el campo @LastID para el siguiente registro. Ahora, el siguiente registro para el cliente... El último ID es el mismo, por lo que toma el @SeqNo (ahora =1) y suma 1 a 1 y se convierte en el número 2 para el mismo cliente... Continúe por el camino... .

En cuanto a mejorar en la escritura de consultas, eche un vistazo a la etiqueta MySQL y observe algunos de los grandes contribuyentes. Mire las preguntas y algunas de las respuestas complejas y cómo funciona la resolución de problemas. No quiere decir que no haya otros con puntajes de reputación más bajos que recién comienzan y son completamente competentes, pero encontrará quién da buenas respuestas y por qué. Mire su historial de respuestas publicadas también. Cuanto más lea y siga, más aprenderá a escribir consultas más complejas.