【问题标题】:PHP SQL query slow?PHP SQL查询慢?
【发布时间】:2026-02-03 03:10:02
【问题描述】:

这是我用来取消关注用户的功能。

    首先删除用户之间的关系以及与该关系相关的所有通知。
    然后它插入一个新的通知给我们要取消关注的用户,然后更新他的关注者计数(因为一个关注者已经离开)。
我正在使用 multi_query,这个查询在大型数据库上似乎有点慢,我想知道这是否是一个好习惯,或者是否有任何更复杂的查询形式来完成工作.

PHP 函数

// 'By' is the array that hold logged user and 'followed' is the user id which we are going to unfollow
function unFollowUser($followed,$by) {
    $following = $this->getUserByID($followed);// Return fetch_assoc of user row
    if(!empty($following['idu'])) { // if user exists

        // return user followers as number of rows
        $followers = $this->db->real_escape_string($this->numberFollowers($following['idu'])) - 1;  

        $followed_esc = $this->db->real_escape_string($following['idu']);
        $by_user_esc = $this->db->real_escape_string($by['idu']);

        // delete relationship
        $query = "DELETE FROM `relationships` WHERE `relationships`.`user2` = '$followed_esc' AND `relationships`.`user1` = '$by_user_esc' ;" ;

        // delete notification (user started following you )
        $query.= "DELETE FROM `notifications` WHERE `notifications`.`not_from` = '$by_user_esc' AND `notifications`.`not_to` = '$followed_esc' ;" ;

        // Insert a new notification( user has unfollowed you)
        $query.= "INSERT INTO `notifications`(`id`, `not_from`, `not_to`, `not_content_id`,`not_content`,`not_type`,`not_read`, `not_time`) VALUES (NULL, '$by_user_esc', '$followed_esc', '0','0','5','0', CURRENT_TIMESTAMP) ;" ;

        // update user followers (-1)
        $query .= "UPDATE `users` SET `followers` = '$followers' WHERE `users`.`idu` = '$followed_esc' ;" ;

        if($this->db->multi_query($query) === TRUE) {
            return 1;
        } else {
            return 0;
        }
    } else {
        return 0;
    }
}

表结构

--
-- Table structure for table `notifications`
--

CREATE TABLE IF NOT EXISTS `notifications` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `not_from` int(11) NOT NULL,
  `not_to` int(11) NOT NULL,
  `not_content_id` int(11) NOT NULL,
  `not_content` int(11) NOT NULL,
  `not_type` int(11) NOT NULL,
  `not_read` int(11) NOT NULL,
  `not_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  UNIQUE KEY `id` (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

--
-- Table structure for table `relationships`
--

CREATE TABLE IF NOT EXISTS `relationships` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user1` int(11) NOT NULL,
  `user2` int(11) NOT NULL,
  `status` int(11) NOT NULL,
  `time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

--
-- Table structure for table `users`
--

CREATE TABLE IF NOT EXISTS `users` (
  `idu` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(32) NOT NULL,
  `password` varchar(256) NOT NULL,
  `email` varchar(256) NOT NULL,
  `first_name` varchar(32) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
  `last_name` varchar(32) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
  `verified` int(11) NOT NULL,
  `posts` text CHARACTER SET utf32 NOT NULL,
  `photos` text CHARACTER SET utf32 NOT NULL,
  `followers` text CHARACTER SET utf32 NOT NULL,
  UNIQUE KEY `id` (`idu`),
  UNIQUE KEY `idu` (`idu`)
  ) ENGINE=InnoDB  DEFAULT CHARSET=latin1;

【问题讨论】:

    标签: php sql mysqli


    【解决方案1】:

    在我的测试中,multi_query 是执行多个不同查询的最快方式。为什么感觉它运行缓慢?相比什么?

    无论如何,改进可能来自为您经常搜索的某些列添加索引:

    • relationships.users2
    • relationships.users1
    • notifications.not_from
    • notifications.not_to
    • users.idu

    添加索引可以加快搜索速度,但它至少有两个缺点:

    • 使数据库消耗更多资源,这可能会影响您的服务器性能
    • 使写入操作花费更长的时间

    我认为您当前的查询没有任何问题。真正考虑您看到的缓慢性能是来自数据库查询本身,还是来自您的 PHP 进程的其余部分。尝试使用查询测量脚本时间,然后跳过查询并进行另一次测量(您可以对查询结果进行硬编码)。它会让您了解缓慢是否是由其他原因造成的。

    无论哪种方式,基准测试。

    【讨论】:

      【解决方案2】:

      尝试在正在运行删除的用户上创建索引,这可能会加快查询速度

      【讨论】:

      • DELETE 语句仅在 notifications 表上运行。
      • notificationsrelationships 表都包含比 users 表大得多的数据(两者都几乎 1000 x users)。