[英]What Indexes do I need to add?
我正在尝试加快此查询的速度,并且除了最后一部分之外,我拥有所需的所有索引/外键。
查看type
列,我可以看到pb
正在查看all
记录,我需要纠正all
记录。
我想知道您是否可以帮助我找出我需要的其他索引/FK,当然,如果您有任何一般性的指示,请告诉我。
询问:
explain SELECT
*
FROM `Publish` AS pb
LEFT JOIN Positions AS p ON pb.`Position_ID` = p.`Position_ID`
LEFT JOIN PositionDetails AS pd ON pb.PositionDetail_ID = pd.PositionDetail_ID
LEFT JOIN Posts AS ps ON pb.`Post_ID` = ps.`Post_ID`
INNER JOIN Users AS u ON pb.`User_ID` = u.`User_ID`
LEFT JOIN PublishWatch AS pw ON (p.`Position_ID` = pw.`Position_ID` OR ps.Post_ID = pw.Post_ID ) AND 1=pw.`User_ID`
LEFT JOIN UserFollow AS uf ON pb.User_ID = uf.FollowUser_ID AND 1= uf.`User_ID`
ORDER BY pb.Published desc
limit 0,50
解释输出:
完整的原始查询(在 php 中):
$StrategiesWhere1 = "";
if (isset($_POST["Strategies"]) && sizeof($_POST["Strategies"]) > 0) {
$in1 = "";
$whereIn = [];
foreach ($_POST["Strategies"] as $i => $item) {
$key1 = ":1id" . $i;
$param[$key1] = $item; // collecting values into key-value array
array_push($whereIn, $key1);
}
$StrategiesWhere1 = "AND p.PositionType_ID in (" . implode(",", $whereIn) . ")";
}
$sql = "SELECT
pb.User_ID AS USERID,
p.*,
p.CommentCount as PositionCommentCount,
p.WatchCount as PositionWatchCount,
n.Note,
pt.Strategy,
pt.isUndefinedRisk,
a.Name,
u.Display,
u.AllPosts as UserAllPosts,
u.AllPositions as UserAllPositions,
u.AllComments as UserAllComments,
u.isPro,
u.isSupporter,
ps.*,
ps.CommentCount as PostCommentCount,
ps.WatchCount as PostWatchCount,
pb.Published,
pb.Publish_ID,
pw.PublishWatch_ID,
pw.AllComments AS PublishWatchAllComments,
pd.isClosing,
pd.isOpening,
pd.Price,
uf.AllComments AS UserFollowAllComments,
uf.FollowUser_ID,
uf.UserFollow_ID
FROM `Publish` AS pb
LEFT JOIN Positions AS p ON pb.`Position_ID` = p.`Position_ID`
LEFT JOIN PositionDetails AS pd ON pb.PositionDetail_ID = pd.PositionDetail_ID
LEFT JOIN Posts AS ps ON pb.`Post_ID` = ps.`Post_ID`
LEFT JOIN PositionTypes AS pt ON p.`PositionType_ID` = pt.`PositionType_ID`
LEFT JOIN Accounts AS a ON p.`Account_ID` = a.`Account_ID`
INNER JOIN Users AS u ON pb.`User_ID` = u.`User_ID`
LEFT JOIN Notes AS n ON p.`LastestNote_ID` = n.`Note_ID`
LEFT JOIN PublishWatch AS pw ON (pb.`Position_ID` = pw.`Position_ID` OR pb.Post_ID = pw.Post_ID ) AND :User_ID4 = pw.`User_ID`
LEFT JOIN UserFollow AS uf ON pb.User_ID = uf.FollowUser_ID AND :User_ID5 = uf.`User_ID`
WHERE
(
(
:Type1 in ('Both','Only Positions')
AND p.`Position_ID` IS NOT NULL
AND p.`Security` LIKE :Security
" . $StrategiesWhere1 . "
)
OR
(
p.`Position_ID` IS NULL
)
)
-- Posts Filters
AND
(
(
:Type2 in ('Both','Only Posts')
AND ps.Post_ID IS NOT NULL
AND (
ps.Post like :PostContains1
OR ps.Subject like :PostContains2
)
OR
(
ps.Post_ID IS NULL
)
)
)
-- User Display name
AND
(
(
:Display1 != ''
AND u.Display = :Display2
)
OR
(
:Display3 = ''
)
)
-- Account
AND
(
(
:Account1 != ''
AND a.Name = :Account2
)
OR
(
:Account3 = ''
)
)
-- Only Watching
AND
(
(
:Watching1 = 'Both'
)
OR
(
:Watching2 = 'Only Watched'
AND pw.PublishWatch_ID IS NOT NULL
)
OR
(
:Watching3 = 'Only Unwatched'
AND pw.PublishWatch_ID IS NULL
)
)
-- Pro Limitations
AND
(
(
-- If this is pro they get everything
:isPro1 = 1
)
OR
(
-- Or if this isnt me
u.User_ID != 1
)
OR
(
-- If this is me and its on the small account
-- or a post
u.User_ID = 1
AND
( a.Account_ID = 1
OR
pb.Position_ID is null)
)
OR
(
-- If this is not pro and this is my publish and it isnt the small account or post
-- only show closing trade
u.User_ID = 1
AND a.Account_ID != 1
AND p.Closed is not null
)
)
ORDER BY pb.Published desc
limit :Offset,:Count;
";
使用 Thorsten 提供的密钥更新说明:
首先,我会将Positions
和Posts
的连接条件放到它们所属的ON
子句中:
LEFT JOIN Positions AS p ON pb.Position_ID = p.Position_ID
AND :Type1 in ('Both', 'Only Positions')
AND p.Security LIKE :Security
" . $StrategiesWhere1 . "
LEFT JOIN Posts AS ps ON pb.Post_ID = ps.Post_ID
AND :Type2 in ('Both', 'Only Posts')
AND
(
ps.Post like :PostContains1
OR
ps.Subject like :PostContains2
)
在我看来有点可疑的一件事是:您选择了Positions
和PositionDetails
,但两者似乎并不相关。 根据表名,我希望您只需要与PositionDetails
具有相同Position_ID
Positions
,但可能PositionDetails
没有Position_ID
。 这可能是一个问题,如果是,我不确定这是否真的是查询的问题,还是数据模型的问题。
至于表现; 这个
ORDER BY pb.Published desc
limit :Offset,:Count;
可能会很慢。 这样做是获取整个结果集(我不知道在您的情况下这是数十行、数百行还是数千行),然后对完整集进行排序以获得所需的子集。 如果您想要前 50 行或后 50 行或后 50 行,这并不重要; DBMS 将始终必须选择完整的数据集并对其进行排序以返回所需的行。
您的所有联接仅将一个表行连接到一个Publish
行,但PublishWatch
除外,其中同一用户可以同时查看位置和帖子,在这种情况下,您会为一个Publish
行获得两个结果行,而不是只有一个。 因此,您可以请求接下来的 50 个Published
日期/时间,而不是请求接下来的 50 行:
WHERE pb.Published > :last_max_published
ORDER BY pb.Published desc
limit :Count;
因此,您将始终只查看剩余的行,而不必对已经处理过的所有行进行排序。
至于索引,您可以尝试以下操作。 其中一些覆盖索引,即它们包含查询中使用的所有列。 这意味着如果 DBMS 使用这些索引,它就不必读取表。 您可以提供所有这些索引,然后检查使用了哪些索引,然后删除其他索引。
CREATE INDEX idx01 ON Users(Display, User_ID);
CREATE INDEX idx02 ON Accounts(Name, User_ID, Account_ID);
CREATE INDEX idx03 ON Positions(Position_ID, Closed);
CREATE INDEX idx04 ON PublishWatch(User_ID, Position_ID, Post_ID, PublishWatch_ID, AllComments);
CREATE INDEX idx05 ON UserFollow(User_ID, FollowUser_ID);
CREATE INDEX idx06 ON UserFollow(FollowUser_ID, User_ID);
CREATE INDEX idx07 ON Positions(Position_ID, Security);
CREATE INDEX idx08 ON Posts(Post_ID, Post, Subject);
CREATE INDEX idx09 ON Accounts(Account_ID, Name);
CREATE INDEX idx10 ON Notes(Note_ID, Note);
CREATE INDEX idx11 ON PositionTypes(PositionType_ID, isUndefinedRisk, Strategy);
CREATE INDEX idx12 ON Publish(Published);
首先,我建议学习如何阅读数据库平台的执行计划。 在对查询进行故障排除时,这是一个不错的起点。 执行计划通常共享哪些索引可以帮助优化查询。 但是请注意不要只添加索引,因为这可能会无意中影响其他查询的性能。
您当前查询的一些提示:
*
用于消耗资源的多个表返回。最好的祝愿!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.