2015-02-06 86 views
1

我知道在不知道模型的情况下很难回答,但我有下一个大量查询需要大约10秒才能在我的MySQL数据库中完成。我想它可以优化,但我不熟练。SQL优化(MySQL)

SELECT DISTINCT 
    b . * 
FROM 
    boats b, 
    states s, 
    boat_people bp, 
    countries c, 
    provinces pr, 
    cities ct1, 
    cities ct2, 
    ports p, 
    addresses a, 
    translations t, 
    element_types et 
WHERE 
    s.name = 'Confirmed' AND bp.id = '2' 
     AND b.state_id = s.id 
     AND b.id NOT IN (SELECT 
      bc.boat_id 
     FROM 
      boat_calendars bc 
     WHERE 
      (date(bc.since) <= '2015-02-09 09:23:00 +0100' 
       AND date(bc.until) >= '2015-02-09 09:23:00 +0100') 
       OR (date(bc.since) <= '2015-02-10 09:23:00 +0100' 
       AND date(bc.until) >= '2015-02-10 09:23:00 +0100')) 
     AND b.people_capacity_id >= bp.id 
     AND c.id = (SELECT DISTINCT 
      t.element_id 
     FROM 
      translations t, 
      element_types et 
     WHERE 
      t.element_translation = 'Spain' 
       AND et.name = 'Country' 
       AND t.element_type_id = et.id) 
     AND pr.country_id = c.id 
     AND pr.id = (SELECT DISTINCT 
      t.element_id 
     FROM 
      translations t, 
      element_types et 
     WHERE 
      t.element_translation = 'Mallorca' 
       AND et.name = 'Province' 
       AND t.element_type_id = et.id) 
     AND ((ct1.province_id = pr.id AND p.city_id = ct1.id AND b.port_id = p.id) 
     OR (ct2.province_id = pr.id AND a.city_id = ct2.id AND b.address_id = a.id)); 

基本上,它试图让所有的船,那是不是已经预订了确认状态,并且是在一个省,一个国家,即。马略卡岛,西班牙。

请让我知道你是否需要关于查询或模型的目的的更多细节。

+1

删除'*'而不是在'select'语句中给出'列名'。它会增加一些性能。其优化 – 2015-02-06 09:01:41

+1

的方法之一是否在连接的列上定义了索引? – 2015-02-06 09:06:31

+0

您对_translations_和_element_types_有交叉连接。这两个表都不在主查询中使用,并且没有连接条件来限制连接。 – Kickstart 2015-02-06 09:42:59

回答

1

从select子句中删除*。而是在select子句中给出列名。它会增加一些 的表现。它的优化方法之一

1

而不是有一个子查询,使用LEFT JOIN NULL(只是谷歌它),它会帮助很多。

0

你所有的答案都很好。但是,根据@POHH的建议,我通过替换b。* for b.somecolumnsnames来神奇地提高了性能。

从10到1或2秒。

+0

很高兴它可以帮助你。 – 2015-02-06 10:08:41

+0

你可以检查它作为答案,然后...:第 – 2015-02-06 10:12:54