【问题标题】:Anyway to optimize following query?无论如何优化以下查询?
【发布时间】:2014-06-25 17:00:06
【问题描述】:

我在数据库帐户、产品和用户中有三个表。我编写的以下查询执行时间过长。无论如何要优化以下查询?

"SELECT accounts.id AS aucID, accounts.product_id, accounts.end_time, accounts.price, accounts.win_id, 
products.id, products.title, products.ratio, users.id , users.username, users.gender, users.email, users.ip
FROM accounts, products, users
WHERE products.id
IN (
SELECT id
FROM products
WHERE accounts.product_id = id
)
AND users.id
IN (
SELECT id
FROM users
WHERE accounts.win_id = id
)
AND accounts.end_time >= '$monday'

AND accounts.end_time < '$sunday'

GROUP BY accounts.end_time"

【问题讨论】:

  • 您使用 PHP 通过字符串插值创建 SQL 语句。这是各种各样的错误。改进这一点的第一种方法是将其转换为参数化查询。如果您想进行有意义的更改,请阅读有关 SQL 注入以及有关 mysqli 和查询参数的信息。

标签: mysql


【解决方案1】:

试试INNER JOIN

SELECT accounts.id AS aucID,
       accounts.product_id,
       accounts.end_time,
       accounts.price,
       accounts.win_id,
       products.id,
       products.title,
       products.ratio,
       users.id ,
       users.username,
       users.gender,
       users.email,
       users.ip
FROM accounts
INNER JOIN products ON accounts.product_id = products.id
INNER JOIN users ON accounts.win_id = users.id
WHERE accounts.end_time >= '$monday'
  AND accounts.end_time < '$sunday'
GROUP BY accounts.end_time

【讨论】:

    【解决方案2】:

    为什么不简化这个 -

     SELECT 
        accounts.id AS aucID, 
        accounts.product_id, 
        accounts.end_time, 
        accounts.price, 
        accounts.win_id, 
        products.id, 
        products.title, 
        products.ratio, 
        users.id , 
        users.username, 
        users.gender, 
        users.email, 
        users.ip
     FROM accounts, products, users
     WHERE accounts.product_id = products.id
     AND accounts.win_id = users.id
     AND accounts.end_time >= '$monday'
     AND accounts.end_time < '$sunday'
     GROUP BY accounts.end_time
    

    您也可以考虑在以下列中创建索引:

    accounts.product_id 
    accounts.win_id 
    accounts.end_time
    

    【讨论】:

    • 旧式连接语法来自上一个千年
    • @Tomalak 是吗?对性能有影响吗?参考 - stackoverflow.com/questions/1613304/…
    • 我是说这已经被永远弃用了,并不是说它变慢了。
    【解决方案3】:

    您需要使用显式 JOIN 而不是隐式。

    select 
    a.id as aucID,
    a.product_id ,
    a.end_time,
    a.price,
    a.win_id,
    p.id,
    p.title,
    p.ratio,
    u.id as user_id
    u.username,
    u.gender,
    u.email,
    u.ip
    from accounts a
    join products p on p.id = a.product_id
    join users u on u.id = a.win_id
    WHERE 
    a.end_time >= '$monday'
    and a.end_time < '$sunday'
    GROUP BY a.end_time
    

    现在你需要索引所以首先检查

    show indexes from accounts;
    show indexes from accounts;
    show indexes from users;
    

    如果不添加以下索引,请检查列是否已被索引。

    alter table accounts add index product_id_idx(product_id);
    alter table accounts add index win_id_idx(win_id);
    alter table accounts add index end_time_idx(end_time);  
    alter table products add index pid_idx(id);
    alter table users add index uid_idx(id);
    

    请注意,默认情况下主键是索引的,因此您可以避免在索引上进行索引

    alter table products add index pid_idx(id);
    alter table users add index uid_idx(id);
    

    如果它们被设置为主键。

    此外,请确保 JOINING 键始终具有相同的数据类型

    例如

    join products p on p.id = a.product_id
    

    p.id 和 a.product_id 应该具有相同的数据类型 ex : int

    类似

    join users u on u.id = a.win_id
    

    更改后查看查询性能。

    【讨论】:

      猜你喜欢
      • 2012-09-28
      • 2012-08-21
      • 1970-01-01
      • 2020-05-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-04
      • 2021-11-19
      相关资源
      最近更新 更多