mysql - MySQL 查询 153 秒,我做错了什么?

标签 mysql

我有一个包含下表的数据库

german_akkusativ_plural [ akkusativ_plural, word_id ]
german_akkusativ_singular [ akkusativ_singular, word_id ]
german_dativ_plural [ dativ_plural, word_id ]
german_dativ_singular [ dativ_singular, word_id ]
german_gender [ gender, word_id ]
german_genitiv_plural [ genitiv_plural, word_id ]
german_genitiv_singular [ genitiv_singular, word_id ]
german_nominativ_plural [ nominativ_plural, word_id ]
german_nominativ_singular [ nominativ_singular, word_id ]
german_word [ id, word, blacklisted ]

下面的查询应该找到一个单词对应的性别(该单词可以是其中一种情况)

SELECT gg.gender
    FROM german_word gw
        INNER JOIN 
            german_nominativ_singular gns
            ON gw.id = gns.word_id
        INNER JOIN 
            german_nominativ_plural gnp
            ON gw.id = gnp.word_id
        INNER JOIN 
            german_akkusativ_singular gas
            ON gw.id = gas.word_id
        INNER JOIN 
            german_akkusativ_plural gap
            ON gw.id = gap.word_id
        INNER JOIN 
            german_dativ_singular gds
            ON gw.id = gds.word_id
        INNER JOIN 
            german_dativ_plural gdp
            ON gw.id = gdp.word_id
        INNER JOIN 
            german_genitiv_singular ggs
            ON gw.id = ggs.word_id
        INNER JOIN 
            german_genitiv_plural ggp
            ON gw.id = ggp.word_id
        INNER JOIN 
            german_gender gg
            ON gw.id = gg.word_id
    WHERE 
        gns.nominativ_singular = 'Auto' OR
        gnp.nominativ_plural = 'Auto' OR
        gas.akkusativ_singular = 'Auto' OR
        gap.akkusativ_plural = 'Auto' OR
        gds.dativ_singular = 'Auto' OR
        gdp.dativ_plural = 'Auto' OR
        ggs.genitiv_singular = 'Auto' OR
        ggp.genitiv_plural = 'Auto'

问题是,当我在 phpMyAdmin 中运行查询时,需要大约 150 秒才能运行。这是为什么?我对除“黑名单”之外的所有字段都有索引。

这是正确的方法还是我完全偏离了轨道?

我将非常感谢任何帮助!谢谢。

编辑:

这是 EXPLAIN 的输出

id  select_type table   type    possible_keys               key     key_len ref                         rows    Extra
1   SIMPLE      gg      ALL     word_id                     NULL    NULL    NULL                        41522   
1   SIMPLE      gdp     ref     dativ_plural,word_id        word_id 5       usr_web410_3.gg.word_id     1       Using where
1   SIMPLE      ggp     ref     genitiv_plural,word_id      word_id 5       usr_web410_3.gg.word_id     1       Using where
1   SIMPLE      gap     ref     akkusativ_plural,word_id    word_id 5       usr_web410_3.gg.word_id     1       Using where
1   SIMPLE      gnp     ref     nominativ_plural,word_id    word_id 5       usr_web410_3.ggp.word_id    1       Using where
1   SIMPLE      gas     ref     akkusativ_singular,word_id  word_id 5       usr_web410_3.gg.word_id     1       Using where
1   SIMPLE      gns     ref     nominativ_singular,word_id  word_id 5       usr_web410_3.gg.word_id     1       Using where
1   SIMPLE      gds     ref     dativ_singular,word_id      word_id 5       usr_web410_3.gns.word_id    1       Using where
1   SIMPLE      ggs     ref     genitiv_singular,word_id    word_id 5       usr_web410_3.gg.word_id     1       Using where
1   SIMPLE      gw      eq_ref  PRIMARY                     PRIMARY 4       usr_web410_3.gg.word_id     1       Using index

最佳答案

您正在获取每个表中的每一行,然后检查是否有任何表与'Auto'匹配。这很慢。这些OR对性能不利,因此您必须放弃它们。

有很多方法可以重写您的查询,我只推荐一种。 首先,我认为没有理由使用 german_word 表。它不存在于任何 where 或 select 子句中,因此我们可以只使用 german_gender 表。请记住,更大的 SQL 查询并不一定意味着性能更差。

试试这个。它应该更快地带来相同的结果。我假设所有文本列(例如 nominativ_singular)都已建立索引。

SELECT gg.gender as gender
FROM german_gender gg
    INNER JOIN german_nominativ_singular gns
    ON gg.word_id = gns.word_id AND gns.nominativ_singular = 'Auto'
UNION  
SELECT gg.gender as gender
FROM german_gender gg
    INNER JOIN german_nominativ_plural gnp
    ON gg.word_id = gnp.word_id AND gnp.nominativ_plural = 'Auto' 
UNION  
SELECT gg.gender as gender
FROM german_gender gg
    INNER JOIN german_akkusativ_singular gas
    ON gg.word_id = gas.word_id AND gas.akkusativ_singular = 'Auto' 
UNION  
SELECT gg.gender as gender
FROM german_gender gg
    INNER JOIN german_akkusativ_plural gap
    ON gg.word_id = gap.word_id AND gap.akkusativ_plural = 'Auto' 
UNION  
SELECT gg.gender as gender
FROM german_gender gg
    INNER JOIN german_dativ_singular gds
    ON gg.word_id = gds.word_id AND gds.dativ_singular = 'Auto' 
UNION  
SELECT gg.gender as gender
FROM german_gender gg
    INNER JOIN german_dativ_plural gdp
    ON gg.word_id = gdp.word_id AND gdp.dativ_plural = 'Auto' 
UNION  
SELECT gg.gender as gender
FROM german_gender gg
    INNER JOIN german_genitiv_singular ggs
    ON gg.word_id = ggs.word_id AND ggs.genitiv_singular = 'Auto' 
UNION  
SELECT gg.gender as gender
FROM german_gender gg
    INNER JOIN german_genitiv_plural ggp
    ON gg.word_id = ggp.word_id AND ggp.genitiv_plural = 'Auto'

关于mysql - MySQL 查询 153 秒,我做错了什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20373240/

相关文章:

mysql - 如何使用带有force选项的mysql source命令

php SELECT (count) in mysql/pdo WHERE 格式化日期

php - 如何获取除特定值之外的所有行

MySQL group by after union #1064 错误

mysql - 统计生成超过 2 张发票的客户 - mysql

sql - 替换文本字段中的字符串

mysql - CloudSQL 数据库定期崩溃(内存不足)

MySQL:如何通过转换 VARCHAR 列中的所有值来设置 DATE 列?

php - 密码验证无法将散列密码与用户输入的密码进行比较

php - 更新值等于的值