SQL优化左外部联接查询

时间:2018-09-11 00:49:05

标签: php mysql sql query-optimization

首先,感谢您抽出宝贵的时间阅读和发布所有回复,谢谢!!

我有两个表,一个用于属性,其中存储有关每个属性/状态的信息。另一个表是用于Translations的,其中存储着用户决定编写的每种语言的数据,例如标题和描述。

在“属性”表中,t_reference列会将翻译的“参考”存储在“翻译”表中。这是一个数字值,如果该特定项目没有翻译,则为0。

在Translations表中,先前的t_reference被存储为'reference'。表格输出:

id  int(11)
reference   mediumint(9)
lang    varchar(5)
is_default  tinyint(4)
t_title     varchar(255)
t_description   text 

现在,要获取信息,我正在使用以下查询:

SELECT
    p.id,
    p.t_reference,
    p.category,
    IFNULL(tr.t_title, def.t_title) 'title',
    IFNULL(tr.t_description, def.t_description) 'description'
FROM properties p
LEFT OUTER JOIN translations tr
    ON (p.t_reference > 0 AND p.t_reference = tr.reference AND tr.lang = 'de_DE')
LEFT OUTER JOIN translations def
    ON (p.t_reference > 0 AND p.t_reference = def.reference AND def.is_default = 1)
WHERE p.visibility='1'

p是属性表,tr是翻译表数据(如果存在翻译),def是翻译表数据的默认语言。 我遇到的问题是,拥有300多个属性,此查询将页面渲染速度提高了约80ms。

我正在尝试为客户实施多语言输入。以前,每个属性的标题和描述只是保存在一列中,但是现在,由于客户应该可以选择输入不同语言的特定文本,而不是使用诸如“ title_en”,“ title_de”之类的硬编码列,我认为这将是最好的方法。唯一的问题是查询的速度。

首先,有没有一种方法可以改善此查询以加快流程?

第二,将其视为不好的做法,而不是在查询本身中使用JOIN。首先获取所有属性数据,然后对通过引用搜索的翻译表运行单独的查询。

1 个答案:

答案 0 :(得分:1)

首先编写如下查询:

class InfiniteGenerator(object):
    def __init__(self, alist):
        self.alist = alist

    def __getitem__(self, idx):
        return self.alist[idx]

    def __len__(self):
        return len(self.alist)

    def __iter__(self):
        for item in (self[i] for i in range(len(self))):
            yield item

from keras.utils import Sequence

class KGen(Sequence):
    def __init__(self, alist):
        self.alist = alist

    def __getitem__(self, idx):
        return self.alist[idx]

    def __len__(self):
        return len(self.alist)


if __name__ ==  '__main__':
    ig = InfiniteGenerator(list(range(4)))
    for item in ig:
        print(item)


    print('now trying second iterator')

    import time
    time.sleep(1)

    kg = KGen(list(range(4)))
    for item in kg:
        print(item)

请注意更改:

  • SELECT p.id, p.t_reference, p.category, COALESCE(tr.t_title, def.t_title) as title, COALESCE(tr.t_description, def.t_description) as description FROM properties p LEFT OUTER JOIN translations tr ON p.t_reference = tr.reference AND tr.lang = 'de_DE' LEFT OUTER JOIN translations def ON p.t_reference = def.reference AND def.is_default = 1 WHERE p.visibility = 1 AND -- guessing visibility is a number p.t_reference > 0 -- guessing this is a filtering condition 周围没有引号,因为'1'可能是数字。
  • visibility条件移动到p.t_reference > 0子句。因为这是在第一个表上,所以可能是过滤条件。
  • WHERE相比,我更喜欢COALESCE(),因为前者是SQL中的ISO / ANSI标准函数。

您希望在以下位置建立索引:

  • IFNULL()
  • properties(visibility, t_reference)