没有临时表

时间:2015-11-03 07:03:45

标签: query-optimization mariadb

我有一个FIFO作业队列,可以增长到0到10MM的记录范围。每条记录都有一些与用户相关的值。我有一个第二个表,可以包含优先级的USERS。工作线程会对此进行大量查询。当按此优先级排序时,这会导致1MM记录范围内的慢查询,例如

select  *
    from  calcqueue
    LEFT JOIN  calc_priority USING(userId)
    where  calcqueue.isProcessing IS NULL
    order by  ISNULL(calc_priority.priority), calc_priority.priority

运行解释就可以得到我" Using index condition; Using temporary; Using filesort"。我试图将其切换到派生表,该表可以扩展到更大的行数,但是我无法保持保留的顺序,这会破坏真正的意图(但至少可以使我的服务器保持快速)

SELECT  *
    FROM  
      ( SELECT  priority,p,userId FROM
              ( SELECT  calc_priority.priority,
                        qt_uncalc.userId,
                        ISNULL(calc_priority.priority) p
                    from  
                      ( SELECT  userId
                            from  calcqueue
                            WHERE  isProcessing IS NULL
                      ) qt_uncalc
                    LEFT JOIN  calc_priority USING(userId) sortedQ
                    ORDER BY  p,sortedQ.priority ASC
              ) orderedT 

无论如何只能使用派生表来实现这一目标吗? calc_priority可以(并确实)改变很多。因此,在calcqueue插入时添加优先级不是一个选项

1 个答案:

答案 0 :(得分:1)

计划A

蒙克:

      ( SELECT  *, 999999 AS priority
            from  calcqueue
            LEFT JOIN  calc_priority USING(userId)
            where  calcqueue.isProcessing IS NULL
              AND  calc_priority.priority IS NULL
            LIMIT  10 
      )
    UNION  ALL
      ( SELECT  *, calc_priority.priority
            from  calcqueue
            JOIN  calc_priority USING(userId)
            where  calcqueue.isProcessing IS NULL
            ORDER BY  calc_priority.priority
            LIMIT  10 
      )
    ORDER BY  priority

并包含

    LIMIT  10; INDEX(isProcessing, userId)

我试图避免NULL的麻烦。

计划B

您可以将应用更改为始终将priority设置为合适的值,从而避免必须执行UNION