当前位置: 首页 > 知识库问答 >
问题:

清晰的内部连接缓慢

郭星文
2023-03-14

我已经编写了下面的PostgreSQL查询,它可以正常工作。然而,它似乎非常慢,有时需要10秒才能返回结果。我确信我的声明中有某种东西导致这一切进展缓慢。

有人能帮助确定为什么这个查询很慢吗?

SELECT DISTINCT ON (school_classes.class_id,attendance_calendar.school_date)
  school_classes.class_id, school_classes.class_name, school_classes.grade_id
, school_gradelevels.linked_calendar, attendance_calendars.calendar_id
, attendance_calendar.school_date, attendance_calendar.minutes
, teacher_join_classes_subjects.staff_id, staff.first_name, staff.last_name  

FROM school_classes 
INNER JOIN school_gradelevels ON school_gradelevels.id=school_classes.grade_id 
INNER JOIN teacher_join_classes_subjects ON teacher_join_classes_subjects.class_id=school_classes.class_id 
INNER JOIN staff ON staff.staff_id=teacher_join_classes_subjects.staff_id 
INNER JOIN attendance_calendars ON attendance_calendars.title=school_gradelevels.linked_calendar 
INNER JOIN attendance_calendar ON attendance_calendar.calendar_id=attendance_calendars.calendar_id 

WHERE teacher_join_classes_subjects.syear='2013' 
AND staff.syear='2013' 
AND attendance_calendars.syear='2013' 
AND teacher_join_classes_subjects.does_attendance='Y' 
AND teacher_join_classes_subjects.subject_id IS NULL 
AND attendance_calendar.school_date<CURRENT_DATE 

AND attendance_calendar.school_date NOT IN (

SELECT com.school_date FROM attendance_completed com
WHERE  com.class_id=school_classes.class_id
AND   (com.period_id='101' AND attendance_calendar.minutes>='151' OR
       com.period_id='95'  AND attendance_calendar.minutes='150') )

我用以下内容替换了not IN

AND NOT EXISTS (
    SELECT com.school_date
    FROM attendance_completed com
    WHERE com.class_id=school_classes.class_id
    AND com.school_date=attendance_calendar.school_date
    AND (com.period_id='101' AND attendance_calendar.minutes>='151' OR
         com.period_id='95'  AND attendance_calendar.minutes='150') )

解释分析结果:

Unique  (cost=2998.39..2998.41 rows=3 width=85) (actual time=10751.111..10751.118 rows=1 loops=1)
  ->  Sort  (cost=2998.39..2998.40 rows=3 width=85) (actual time=10751.110..10751.110 rows=2 loops=1)
        Sort Key: school_classes.class_id, attendance_calendar.school_date
        Sort Method:  quicksort  Memory: 25kB
        ->  Hash Join  (cost=2.03..2998.37 rows=3 width=85) (actual time=6409.471..10751.045 rows=2 loops=1)
              Hash Cond: ((teacher_join_classes_subjects.class_id = school_classes.class_id) AND (school_gradelevels.id = school_classes.grade_id))
              Join Filter: (NOT (SubPlan 1))
              ->  Nested Loop  (cost=0.00..120.69 rows=94 width=81) (actual time=2.468..1187.397 rows=26460 loops=1)
                    Join Filter: (attendance_calendars.calendar_id = attendance_calendar.calendar_id)
                    ->  Nested Loop  (cost=0.00..42.13 rows=1 width=70) (actual time=0.087..3.247 rows=735 loops=1)
                          Join Filter: ((attendance_calendars.title)::text = (school_gradelevels.linked_calendar)::text)
                          ->  Nested Loop  (cost=0.00..40.80 rows=1 width=277) (actual time=0.077..1.005 rows=245 loops=1)
                                ->  Nested Loop  (cost=0.00..39.61 rows=1 width=27) (actual time=0.064..0.572 rows=49 loops=1)
                                      ->  Seq Scan on teacher_join_classes_subjects  (cost=0.00..10.48 rows=4 width=14) (actual time=0.022..0.143 rows=49 loops=1)
                                            Filter: ((subject_id IS NULL) AND (syear = 2013::numeric) AND ((does_attendance)::text = 'Y'::text))
                                      ->  Index Scan using staff_pkey on staff  (cost=0.00..7.27 rows=1 width=20) (actual time=0.006..0.007 rows=1 loops=49)
                                            Index Cond: (staff.staff_id = teacher_join_classes_subjects.staff_id)
                                            Filter: (staff.syear = 2013::numeric)
                                ->  Seq Scan on attendance_calendars  (cost=0.00..1.18 rows=1 width=250) (actual time=0.003..0.006 rows=5 loops=49)
                                      Filter: (attendance_calendars.syear = 2013::numeric)
                          ->  Seq Scan on school_gradelevels  (cost=0.00..1.15 rows=15 width=11) (actual time=0.001..0.005 rows=15 loops=245)
                    ->  Seq Scan on attendance_calendar  (cost=0.00..55.26 rows=1864 width=18) (actual time=0.003..1.129 rows=1824 loops=735)
                          Filter: (attendance_calendar.school_date   Hash  (cost=1.41..1.41 rows=41 width=18) (actual time=0.040..0.040 rows=41 loops=1)
                    ->  Seq Scan on school_classes  (cost=0.00..1.41 rows=41 width=18) (actual time=0.006..0.015 rows=41 loops=1)
              SubPlan 1
                ->  Seq Scan on attendance_completed com  (cost=0.00..958.28 rows=5 width=4) (actual time=0.228..5.411 rows=17 loops=1764)
                      Filter: ((class_id = $0) AND (((period_id = 101::numeric) AND ($1 >= 151::numeric)) OR ((period_id = 95::numeric) AND ($1 = 150::numeric))))

共有1个答案

阎俊英
2023-03-14

不存在是一个很好的选择。几乎总是比不在中要好。这里有更多细节。我把你的问题简化了一点(大体上看起来不错):

SELECT DISTINCT ON (c.class_id, a.school_date)
       c.class_id, c.class_name, c.grade_id
      ,g.linked_calendar, aa.calendar_id
      ,a.school_date, a.minutes
      ,t.staff_id, s.first_name, s.last_name  
FROM   school_classes                c
JOIN   teacher_join_classes_subjects t  USING (class_id)
JOIN   staff                         s  USING (staff_id)
JOIN   school_gradelevels            g  ON g.id = c.grade_id 
JOIN   attendance_calendars          aa ON aa.title = g.linked_calendar 
JOIN   attendance_calendar           a  ON a.calendar_id = aa.calendar_id 
WHERE  t.syear = 2013
AND    s.syear = 2013
AND    aa.syear = 2013
AND    t.does_attendance = 'Y'   -- looks like it should be boolean!
AND    t.subject_id IS NULL 
AND    a.school_date < CURRENT_DATE 
AND NOT EXISTS (
   SELECT 1
   FROM   attendance_completed x
   WHERE  x.class_id = c.class_id
   AND    x.school_date = a.school_date
   AND   (x.period_id = 101 AND a.minutes >= 151 OR  -- actually numbers?
          x.period_id =  95 AND a.minutes  = 150)
   )
ORDER BY c.class_id, a.school_date, ???

似乎缺少的是订购依据,它应该与上的不同。添加更多排序的项目以代替 。如果有重复项可供选择,则可能需要定义要选择的项。

数字文字不需要单引号,布尔值应该这样编码。
您可能想重温关于数据类型的章节。

 类似资料:
  • 问题内容: 只是一个简单的问题: 如何清除外壳中的屏幕?我见过类似的方式: 这只是打开Windows cmd,清除屏幕并关闭,但是我希望清除外壳窗口 (PS:我不知道这有帮助,但是我使用的是Python 3.3.2版) 谢谢:) 问题答案: 对于macOS / OS X,您可以使用子进程模块并从外壳程序中调用“ cls”: 为了防止在窗口顶部显示“ 0”,请用以下内容替换第二行: 对于Linux,

  • 我有一个pyspark数据帧(df1 ),它由10K行组成,数据帧看起来像- 另一个pyspark数据帧(df2)由100k记录组成,看起来像- 我想使用pyspark内连接,最终的数据帧看起来像- df2中mobile_no的长度是12,但df1中是10。我可以加入它,但这是昂贵的操作。使用pyspark有帮助吗?

  • 获得场景视频可为客户转出“普通”“清晰”“高清”“pad”“phone”五种的清晰度,转出越多占用空间越大,您可根据实际需求具体选择。 在该页面,您可为用户设置默认清晰度,以满足效果和成本的平衡。 默认码率和对应视频尺寸见下表: 清晰度规则: · 您上传的视频源文件视频码率高于512kbps或分辨率大于640×480才能转换出高清视频; · 对于多种清晰度的视频,获得场景视频服务平台支持您设置您帐

  • 自动识别图像进行人脸变清晰处理模式一 返回二进制文件流模式二 返回base64字符串模式三 通过图片url返回base64结果 人脸变清晰API调用示例代码 github地址: https://github.com/picup-shop cURL Python PHP Java nodejs .net Objective-C curl -H 'APIKEY: INSERT_YOUR_API_KEY

  • 本文向大家介绍Android清空应用内部文件缓存,包括了Android清空应用内部文件缓存的使用技巧和注意事项,需要的朋友参考一下 Android应用中加载的图片以及一些数据缓存怎么清掉呢?最近在做项目中遇到了这个问题,网上搜了一下找到了不少的源代码,综合了这些源码,下面给大家说一下吧,怎么有效的清除应用内存的缓存信息? 清除应用内部缓存主要包含以下几大模块: 一、清除应用本地所有数据库缓存 二、

  • 问题内容: 好的,这是。我有两个表:product和product_sizes 所以基本上我的产品表具有id(主键),名称(产品名称)和size_id(product_sizes中的外键) 我的product_sizes表具有预定值: 在这里,我有一个有效的代码来显示产品表(使用while代码以html格式): 我的问题是我想显示(用html表示)尺寸名称而不是其size_id,类似于以下示例: