慢MySQL查询/大DB / JOIN

时间:2015-03-27 08:40:28

标签: mysql sql database

有没有办法优化以下MySql查询?

SELECT article.*
FROM article
WHERE channelid = 1
AND ((SELECT count(*) FROM article_cCountry WHERE ID1 = article.id AND ID2 = 1) = 1)
AND date < now()
AND released = "TRUE"
AND ( (uId = 0) OR ((SELECT count(*) FROM user WHERE ID = article.uId and released = true) = 1) )
ORDER BY cDate DESC
LIMIT 20

我已经尝试使用INNER JOIN进行article_cCountry检查,但性能更差。

修改

article_cCountry的结构

| ID | ID1 | ID2 |   (ID1 => article.id, ID2 => country)

用户用户的结构

包含用户数据的约20列

4 个答案:

答案 0 :(得分:1)

我不确定你需要检查

SELECT article.*, COUNT(ac.id) ac_count, COUNT(u.id) u_count
FROM article
  INNER JOIN article_cCountry ac ON ac.ID1 = article.id AND ac.ID2 = 1
  INNER JOIN user u ON u.ID = article.uId and u.released
WHERE 
  channelid = 1
  AND date < now()
  AND released = "TRUE"
GROUP BY article.id
HAVING ac_count = 1 AND (uId = 0 OR u_count = 1)
ORDER BY cDate DESC
LIMIT 20

答案 1 :(得分:0)

尝试使用以下方法解释您的查询:

EXPLAIN SELECT ...

如果您没有使用任何索引,请尝试在where:

中使用的字段上添加索引
article.date
article.channelid
article.released
user.released
article_cCountry.id1
article_cCountry.id2

答案 2 :(得分:0)

试试这个:

  

选择     文章。*   从     文章     INNER JOIN article_cCountry       ON article.id = article_cCountry.ID1     INNER JOIN USER       ON article.uId = USER。身份证   WHERE channelid = 1     AND article_cCountry.ID2 = 1     AND USER。已发布= TRUE     和日期&lt;现在()     AND release = TRUE   订购cDate DESC   限制20;

答案 3 :(得分:0)

尝试将子查询放入临时表

CREATE TEMPORARY TABLE COUNTRY
(
    countryCount INT,
    articleId INT
)
INSERT INTO
    COUNTRY
SELECT
    COUNT(1),
    ID1,
FROM
    article_cCountry
WHERE
    ID2 = 1
GROUP BY
    ID1

CREATE TEMPORARY TABLE USERS
(
    userCount INT,
    articleId INT
)
INSERT INTO
    USERS
SELECT
    COUNT(1),
    ID
FROM
    [user]
WHERE
    released = true
GROUP BY
    ID

SELECT 
    article.*
FROM 
    article JOIN COUNTRY country ON country.articleId = article.id
        JOIN USERS users ON users.articleId = article.uId
WHERE 
    channelid = 1
AND 
    --((SELECT count(*) FROM article_cCountry WHERE ID1 = article.id AND ID2 = 1) = 1)
    country.countryCount = 1
AND 
    date < now()
AND 
    released = "TRUE"
AND 
    ( 
        (uId = 0) 
    OR 
        --((SELECT count(*) FROM user WHERE ID = article.uId and released = true) = 1))
        (users.userCount = 1)
    )
ORDER BY 
    cDate DESC
LIMIT 20

DROP TABLE COUNTRY;
DROP TABLE USERS;