提高子查询的速度

Nin*_*412 3 sql insert derby

此查询运行缓慢,随着表的增长而变慢.谁能找到提高速度的方法?

它旨在用tblUser和tblLesson的id填充tblUser_Lesson,同时确保在insert之前表中不存在id.

我有一个关于tblUser.name和tblLesson.name的索引,但它似乎没有什么区别.

INSERT INTO tblUser_Lesson (user, lesson)
  SELECT userId, lessonId
  FROM
  (
      SELECT tblUser.id userId, tblLesson.id lessonId
      FROM tblUser,
           tblLesson
      WHERE tblUser.name=?
        AND tblLesson.name=?
  ) tmp
  WHERE NOT EXISTS (SELECT user
                    FROM tblUser_Lesson tmp1
                    WHERE tmp1.user = tmp.userId
                      AND tmp1.lesson = tmp.tblLesson)
Run Code Online (Sandbox Code Playgroud)

Gor*_*off 6

这是我发现更容易阅读的查询的等效版本:

INSERT INTO tblUser_Lesson(user, lesson)
    SELECT userId, lessonId
    FROM tblUser u CROSS JOIN
         tblLesson l
    WHERE u.name = ? AND l.name = ? AND
          NOT EXISTS (SELECT 1
                      FROM tblUser_Lesson ul
                      WHERE ul.user = u.userId AND ul.lesson = l.tblLesson
                     );
Run Code Online (Sandbox Code Playgroud)

我的第一个建议是让数据库完成工作.创建一个唯一索引tblUser_Lesson:

create unique index unq_tblUser_Lesson on tblUser_Lesson(UserId, Lesson);
Run Code Online (Sandbox Code Playgroud)

然后只需插入:

INSERT INTO tblUser_Lesson(user, lesson)
    SELECT userId, lessonId
    FROM tblUser u CROSS JOIN
         tblLesson l
    WHERE u.name = ? AND l.name = ? ;
Run Code Online (Sandbox Code Playgroud)

其次,我会为每个其他表创建索引:

create index idx_tbluser_name_id on tblUser(name, id);
create index idx_tblLesson_name_id on tblLesson(name, id);
Run Code Online (Sandbox Code Playgroud)

这加快了这个查询.

如果您(通常)不希望在存在重复时出错,那么您可以保留您的NOT EXISTS条款.索引tblUser_Lesson仍然有用.

  • 很好的解释,我喜欢它 (2认同)