如果表包含10000个条目,如何使用MySQL优化查询?
当我像这样执行这个查询时,它们会占用很多执行时间,因为user\u fans表包含10000users条目。我如何优化它 质疑如果表包含10000个条目,如何使用MySQL优化查询?,mysql,sql,optimization,query-optimization,Mysql,Sql,Optimization,Query Optimization,当我像这样执行这个查询时,它们会占用很多执行时间,因为user\u fans表包含10000users条目。我如何优化它 质疑 您可以将此查询转换为GROUPBY子句,而不是对每列使用子查询 您可以在关系参数上创建索引(这将是优化查询响应的最有用的方法) 您可以将此查询转换为GROUPBY子句,而不是对每列使用子查询 您可以在关系参数上创建索引(这将是优化查询响应的最有用的方法) 1000条用户记录根本算不上什么数据 您可以对数据库本身执行以下操作: 1) 您是否在外键上设置了相关的索引(在每个
1000条用户记录根本算不上什么数据 您可以对数据库本身执行以下操作: 1) 您是否在外键上设置了相关的索引(在每个表中的user_id上设置了索引)?尝试在查询之前运行EXPLAIN
2) 您的数据类型正确吗?1000条用户记录根本不是什么数据 您可以对数据库本身执行以下操作: 1) 您是否在外键上设置了相关的索引(在每个表中的user_id上设置了索引)?尝试在查询之前运行EXPLAIN
2) 您的数据类型正确吗?我会尝试将触发器放在其他表上,然后只向User\u Fans表中添加几列,从而完全简化此操作。。。您试图获取的每个计数()对应一个。。。来自Post、PostLikes、PostComments、PostCommentLikes 当一条记录被添加到任何一个表中时,只需更新您的user_fans表,将1添加到计数中即可。。。无论如何,基于用户的密钥ID,它实际上是即时的。至于“喜欢”。。。类似,仅在某事物被触发为“Like”的情况下,添加1。。然后,您的查询将是对单个记录的直接计算,而不依赖任何联接来计算“加权”总值。当您的表变得更大时,查询也会变得更长,因为它们有更多的数据要倾注和聚合。您正在查看每个user\u fan记录,这实际上是从所有其他表中查询每个记录 话虽如此,保留现有的表格,我将按如下方式进行重组
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
左连接到预查询只运行一次这些查询,然后连接整个查询,而不是作为每个记录的子查询。通过使用COALESCE(),如果在左侧联接的表结果中没有这样的条目,则不会出现空值扰乱计算的情况,因此我将它们默认为000000
澄清您的问题
您可以将任何查询作为“as-AliasResult”。“As”还可用于简化任何长表名,以简化可读性。别名也可以使用同一个表但作为不同的别名来获取相似的内容,但用途不同
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 ...
现在,上面的第三个查询不需要(完整查询导致别名“PQ”表示“PreQuery”)。如果您希望预先限制一组其他复杂条件,并且希望在为所有最终结果对许多其他表进行额外连接之前使用一个较小的集合,则可以这样做
由于“FROM”不必是实际的表,而可以是查询本身,也可以是查询中使用的任何其他位置,因此它必须知道如何引用此预查询结果集
此外,在查询字段时,它们也可以“作为FinalColumnName”,以将结果简化为它们将被使用的地方
挑选
CONCAT(User.saltation,User.LastName)作为courtsyname
从
挑选
订单。不征税
+订单。应税
+(订单.应税*Order.SalesTaxRate)作为OrderTotalWithTax
从
“As”列名不必是聚合,但最常见的情况是这样的
现在,关于MySQL变量。。。如果您正在执行一个存储过程,许多人会在该过程的其余部分之前预先声明它们设置了默认值。您只需设置并为结果提供一个“别名”引用,就可以在查询中在线执行这些操作。执行这些变量时,select将模拟始终返回值的单个记录值。它几乎就像查询中使用的可更新的单个记录。您不需要应用任何特定的“连接”条件,因为它可能与查询中的其他表没有任何关系。。。本质上,创建笛卡尔结果,但一条记录对任何其他表都不会创建重复项,因此不会对下游造成损害
select
...
from
( select @SomeVar := 0,
@SomeDate := curdate(),
@SomeString := "hello" ) as SQLVars
现在,看看sqlvars是如何工作的。想想一个线性规划。。。当查询运行时,一个命令按精确顺序执行。然后将该值重新存储回“SQLVars”记录中,以备下次使用。但是,您不能将其引用为SQLVars.SomeVar或SQLVars.SomeDate。。。只有@SomeVar:=someNewValue。现在,在查询中使用@var时,它也会作为“as ColumnName”存储在结果集中。有时,这可能只是准备下一条记录时占位符计算的值。然后,每个值可直接用于下一行。因此,给定以下示例
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
请注意@SomeVar的值在每列使用时是如何使用的。。。因此,即使在同一条记录上,更新后的值也可以立即用于下一列。。。这就是说,现在看看试图建立一个模拟记录计数/排名每个客户
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
“orderby”子句强制首先按顺序返回结果。因此,这里返回每个客户的记录。第一次通过时,LastID为0,客户ID为…5。由于不同,它将返回1作为@SeqNo,然后将该客户ID保留到@LastID字段中以供下一条记录使用。现在,客户的下一个记录。。。最后一个ID是相同的,因此它采用@SeqNo(现在=1),并将1与1相加,对于同一个客户变成#2。。。继续
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