【问题标题】:How to optimize this sqlrq? Is it proper? How do better?如何优化这个sqlrq?合适吗?怎么做更好?
【发布时间】:2019-06-02 17:43:33
【问题描述】:

感谢您的关注。 整晚都在尽力而为,但没有结果。 我对 mySQL 很陌生。


请告诉我 是否正确构建和优化:

SELECT * 
FROM (
    (`tbl_projects` 
LEFT JOIN `tbl_files` 
    ON ((`file_isforType` = 1) AND `file_isforID`=`proj_uid`) )
INNER JOIN `tbl_users` 
    ON `proj_InitiatorUsrID` = `usr_UID` )
ORDER BY `file_uid` DESC LIMIT 0 , 15

我在上面使用了 EXPLAIN 发现第一张表table_projects没有使用任何key。

我已经把截图放在那里了 =


接下来是数据库的概念。 任何用户都可以发布任意数量的项目和 每个项目都可能有它的图片 (0..x)

项目可能还有一个附件。可能有 1 个或一些,也可能没有。


关节是下一个: project innerjoin 用户 leftjoin 文件

我通过这个 rq 得到了什么:

proj1 | user1 | photo1
proj1 | user1 | photo2
proj1 | user1 | photo3

proj2 | user1 | photo4
proj2 | user1 | photo5

proj3 | user2 | photo6

proj4 | user1 | null

proj5 | user1 | photo7
proj5 | user1 | photo8
proj6 | user2 | null

所以我的 php 脚本从上到下一个接一个 项目的 html 列表中的表单。 有些没有照片。有些有一个。有些有 2,3,4..等等。

proj1 - user1 - 3 photos
proj2 - user1 - 2 photos
proj3 - user2 - 1 photo
proj4 - user1 -  no photos
proj5 - user1 - 2 photos
etc

table_files 在下一个逻辑中构建:

file_uid | file_ownerID | file_isforType| file_isforID
file_uid PRIMARY AI
file_ownerID  reference to PRIMARY at table_users
file_isforType- smallint 1..9
indicates type of THING which this file was attached to.
 eg
1 = _TheProject as project photo
2 = _TheUserProfile as users photo
3 = _TheMessage as attachment

file_ResourceID - unique id of that very thing, whose type specified in file_isforType.

例如

if (file_isWhatfor=_TheProject) AND (file_ResourceID=3)    ->> to the proj#3
if (file_isWhatfor=_TheUserProfile) AND (file_ResourceID=3)    ->> to the user#3
if (file_isWhatfor=_TheMessage) AND (file_ResourceID=3)    ->> to the msg#3

【问题讨论】:

  • 欢迎来到 Stack Overflow!在 proj 和 use 列上使用 GROUP BY,在 photo 列上使用 GROUP_CONCAT() 将大大减少行数,并使 PHP 代码更简单。
  • 如果不知道每列在哪个表中,我们无法判断查询。请根据它们来自哪个表来限定列。
  • 我看到LIMIT 0, 15 -- 你会“分页”吗?

标签: mysql optimization left-join inner-join


【解决方案1】:

我们不可能知道这是否“优化”,因为这需要比您告诉我们的更多的信息。稍后会详细介绍。

虽然 MySQL 确实允许对身份使用反引号,但您不必强制使用 then,除非身份包含空格或保留字。有必要在列名前加上它们的表名或使用表别名。强烈建议这样做(即“最佳实践”),以便您始终知道列来自哪个表。注意我不得不猜测在下面的所有连接中使用哪个表别名,它们可能需要更正。

SELECT 
       *
FROM   tbl_projects AS p
LEFT JOIN tbl_files AS f ON p.proj_uid = f.file_isforID AND f.file_isforType = 1
INNER JOIN tbl_users AS u ON p.proj_InitiatorUsrID = u.usr_UID
ORDER BY f.file_uid DESC 
LIMIT 0 , 15

还请注意,您使用的所有括号都是完全多余的,可以安全地删除。

为了进一步“优化”,我建议你不要使用select *。指定您需要的列,这可以提高结果传输的速度,但不一定对查询执行有任何可衡量的影响。除此之外,您需要在所有连接中涉及的所有列上都有索引,并且您可以使用explain plan 来研究是否缺少索引。见8.8.1 Optimizing Queries with EXPLAIN

如果缺少索引,请考虑将其添加到说明标识的表中。

【讨论】:

  • 关于“最佳实践”)当然你已经注意到每个字段名称都有其父表的前缀并且是唯一的。可以吗?
  • 是的。没关系”。但是,如果您使用自连接或需要对表进行多个连接,则列命名约定不再是一种解决方案。即使按照您的列命名约定,仍然强烈建议您这样做。
猜你喜欢
  • 1970-01-01
  • 2022-01-14
  • 2011-07-01
  • 2011-07-15
  • 1970-01-01
  • 2011-12-26
  • 2016-11-14
  • 1970-01-01
  • 2015-09-06
相关资源
最近更新 更多