使用UNION ALL优化查看视图

时间:2017-10-17 11:04:17

标签: mysql query-optimization

所以我面临一个困难的场景,我有一个遗留应用程序,写得不好,设计不好,有一张桌子,t_booking。这个应用程序有一个日历视图,其中,对于每个大厅,以及该月的每一天,使用此查询显示其预订状态:

SELECT mr1b.id, mr1b.idreserva, mr1b.idhotel, mr1b.idhall, mr1b.idtiporeserva, mr1b.date, mr1b.ampm, mr1b.observaciones, mr1b.observaciones_bookingarea, mr1b.tipo_de_navegacion, mr1b.portal, r.estado 
FROM t_booking mr1b
LEFT JOIN a_reservations r ON mr1b.idreserva = r.id 
WHERE mr1b.idhotel = '$sIdHotel' AND mr1b.idhall = '$hall' AND mr1b.date = '$iAnyo-$iMes-$iDia' 
  AND IF (r.comidacena IS NULL OR r.comidacena = '', mr1b.ampm = 'AM', r.comidacena = 'AM' AND mr1b.ampm = 'AM') 
  AND (r.estado <> 'Cancelled' OR r.estado IS NULL OR r.estado = '') 
LIMIT 1;

(起初还有一个ORDER BY r.estado DESC我拿出来了)

在适当的(我认为)索引之后,此查询每个需要0.004秒,并且整个日历视图在合理的时间内显示。有idhotel,idhall和date的索引。

现在,我有一个新模块,写得很好;-),它在另一个表中进行预订,但我必须在同一个日历视图中显示两种类型的预订。我的第一种方法是创建一个视图,连接两个表的内容,并从该视图而不是t_booking中选择日历视图的数据。

视图的定义如下:

CREATE OR REPLACE VIEW 
t_booking_hall_reservation
AS 
SELECT id, 
        idreserva, 
        idhotel, 
        idhall, 
        idtiporeserva, 
        date, 
        ampm, 
        observaciones, 
        observaciones_bookingarea, 
        tipo_de_navegacion, portal
    FROM t_booking
UNION ALL
SELECT HR.id, 
        HR.convention_id as idreserva, 
        H.id_hotel as idhotel, 
        HR.hall_id as idhall, 
        99 as idtiporeserva, 
        date, 
        session as ampm,
        observations as observaciones,
        'new module' as observaciones_bookingarea, 
        'events' as tipo_de_navegacion, 
        'new module' as portal
FROM new_hall_reservation HR
JOIN a_halls H on H.id = HR.hall_id
;

(表new_hall_reservation具有相同的索引)

我尝试UNION ALL代替UNION,因为我认为这样效率更高。

嗯,之前的查询,t_booking更改t_booking_hall_reservation 1.5秒,每个大厅和每天相乘,使日历视图无法完成。

该应用是spaguetti代码,因此,循环两次,一次超过t_booking,然后超过new_hall_reservation,并且结果合并有些困难。

是否可以调整视图以使此查询足够快?另一种方法?

由于

PS:我修改原始查询的次数越少,我就越不需要修改旧应用程序,这样修改的风险更小

2 个答案:

答案 0 :(得分:0)

评论太长了。

视图(几乎)永远不会帮助提高性能。是的,他们使查询更简单。是的,它们包含重要的逻辑。但不,他们没有帮助表现。

一个关键问题是视图的执行 - 它通常不考虑整个表中的过滤器(尽管最新版本的MySQL在这方面更好)。

一个建议 - 可能是相当多的工作 - 是将视图表示为一个表格。当基础表发生变化时,您需要使用触发器更改t_booking_hall_reservation。然后,您可以在表格上创建索引以实现性能目标。“

答案 1 :(得分:0)

t_booking,除非它是VIEW,需要

INDEX(idhotel, idhall, date)

VIEWs是句法糖;它们不会提高性能;有时它们比等效的SELECT慢。