查询执行时间太长

时间:2014-04-11 15:33:54

标签: php mysql sql

我正在尝试从MySQL数据库中获取学生的所有课程。此片段仅获取1个课程,但总共有6个课程(然后需要15秒)。我正在尝试使用selected标记中的option属性显示已设置的课程(如果有)。我认为这是导致查询执行这么久的原因 我的数据库设计有问题吗?如何改进查询?

这是数据库的结构。我创建了一个中间表 user_courses

用户
user_id

用户_课程
USER_ID
course_id_1
course_id_2
course_id_3
course_id_4
course_id_5
course_id_6
course_id_7

课程
COURSE_ID
course_name

<?php
    session_start();
    $_SESSION['user_id'] = 1;
    require ('../mysqli_connect.php');

    echo '<table><tr><td><select name="course_id_1">';

    // checking if a user has already chosen a 1st course (out of 6)
    $query = "SELECT c.course_id
              FROM courses AS c
              INNER JOIN users_courses AS u
              ON c.course_id = u.course_id_1
              WHERE u.user_id = {$_SESSION['user_id']}";
    $result = mysqli_query($dbc, $query);

    // if yes, assign the selected course from the database to a variable
    if (mysqli_num_rows($result) == 1) {
        $row = mysqli_fetch_array($result, MYSQLI_ASSOC);
        $selected_course = $row['course_id'];
    }

    // fetch courses, and make 'None' the first option in the drop down menu
    $query = "SELECT course_id, course_name 
              FROM courses 
              ORDER BY (course_name = 'None') DESC, course_name";
    $result = mysqli_query($dbc, $query);

    // create the drop down menu
    while ($row = mysqli_fetch_array($result, MYSQLI_ASSOC)) {
        // select default value
        if ($selected_course == $row['course_id']) {
            $selected =' selected';
        } else {
            $selected='';
        }

        echo '<option value="' . $row['course_id'] . '"' . $selected . '>'
              . htmlspecialchars($row['course_name']) . '</option>';
    }

    echo '</select></td></tr>';

    mysqli_free_result($result);
    mysqli_close($dbc); 
?>

2 个答案:

答案 0 :(得分:5)

这里有很多问题。

1)您对表结构的解释不足以诊断一些常见问题,例如缺少索引或您已建立的主键。这些选择会对绩效产生巨大影响。

2)你的users_courses表被非规范化;模拟多对多关系的一种更常见的方法是为每个连接表创建一个带有一个外键的表。在这种情况下,您的表格如下:

USERS_COURSES
-------------
user_id
course_id

然后,拥有7门课程的用户将在该表中拥有7条记录。如果您的模型确实知道诸如“第一选择”之类的优先级,那么您可以使用适当的列扩展连接表。

3)您的PHP代码对SQL injection attacks是敞开的,因为您直接在查询中插入用户输入。您需要解决这个问题并采用始终使用绑定变量的做法

答案 1 :(得分:1)

试试这个...这会创建索引,杰夫提到

CREATE INDEX _index_course ON courses(course_id);
CREATE INDEX _index_user_course ON users_courses(course_id_1);