有没有办法在使用多个表时简化联合查询,参考主表(性能优化)

时间:2016-02-08 14:17:50

标签: mysql sql performance

我想知道有没有办法改进查询,加速/简化使用多个表private int c = 0; ... buttonCycle.addActionListener(e -> label.setIcon(images[c++ % images.length])); 子句时只参考一个主表。

以下是该方案,此处表UNION是我的主要表格,referencegeo_loc1geo_loc2是其他表格,将根据{{1 }}和geo_loc2,这两个键存在于所有表中。

key1

是否可以简化或改进此查询?

2 个答案:

答案 0 :(得分:1)

您可以安全地使用UNION ALL而不是UNION,因为您的查询不能包含任何重复的行。

但是你将主要从良好的索引中获得性能,而不是从编写查询的不同方式中获得性能。

答案 1 :(得分:1)

为了表现,我可以看到你可能会改变的两件事。

1)将UNION更改为UNION ALLUNION会检查重复项的结果,这会增加您不需要的开销。

2)考虑将DATE( reference.st_date ) BETWEEN '2000-07-05' AND '2011-11-10'更改为不使用日期功能。

如果reference.st_date是一个正确的日期列,并且您不需要进行类型转换,那么数据库可以使用基于日期的索引进行快速查找。通过进行类型转换,DB现在必须进行扫描以对每行进行转换。

您说索引在key1,key2,st_date,latitude,longitude上。通过使用日期函数,您可能只使用该索引的前两列。我会将st_date更改为日期或更改您要比较的值,因此不需要转换。

另请考虑使用正确的INNER JOIN,而不是将连接条件添加为WHERE子句。使用正确的语法并且不易出错,它的可读性更高。

使用UNION ALLINNER JOIN的示例应如下所示。请注意,这显然是未经测试的,但你应该明白这一点 编辑删除了使用date()函数,这将进一步加快

SELECT 
    reference.*,
    geo_loc1.bathy,
    geo_loc1.gravity,
    geo_loc1.magnet,
    'data1' as type
FROM 
    reference
INNER JOIN geo_loc1 ON
    reference.key1 = geo_loc1.key1 AND
    reference.key2 = geo_loc1.key2
WHERE
    reference.latitude between -30 and -10 AND 
    reference.longitude between 10 and 50 AND 
    reference.st_date BETWEEN '2000-07-05 00:00:00' AND '2011-11-10 23:59:59'
UNION ALL
SELECT 
    reference.*,
    geo_loc2.bathy,
    Null as gravity,
    geo_loc2.magnet,
    'data2' as type
FROM 
    reference
INNER JOIN geo_loc2 ON
    reference.key1 = geo_loc2.key1 AND
    reference.key2 = geo_loc2.key2
WHERE
    reference.latitude between -30 and -10 AND 
    reference.longitude between 10 and 50 AND 
    reference.st_date BETWEEN '2000-07-05 00:00:00' AND '2011-11-10 23:59:59'
UNION ALL
SELECT 
    reference.*,
    Null as bathy,
    Null as gravity,
    geo_loc3.magnet,
    'data3' as type
FROM 
    reference
INNER JOIN geo_loc3 ON
    reference.key1 = geo_loc3.key1 AND
    reference.key2 = geo_loc3.key2
WHERE
    reference.latitude between -30 and -10 AND 
    reference.longitude between 10 and 50 AND 
    reference.st_date BETWEEN '2000-07-05 00:00:00' AND '2011-11-10 23:59:59'