2016-11-19 32 views
0

我遇到以下查询问题。它从数据库表中选择日志记录。MySQL查询非常慢(20到60秒!) - 为什么?

SELECT paymentslog.*, user.username, user.usergroupid, user.displaygroupid, 
     purchase_temp.threadid 
    FROM " . TABLE_PREFIX . "paymentslog AS paymentslog 
    LEFT JOIN " . TABLE_PREFIX . "user AS user 
     ON (paymentslog.userid = user.userid) 
    LEFT JOIN " . TABLE_PREFIX . "paymenttransaction AS paymenttransaction 
     ON (paymentslog.transactionid = paymenttransaction.transactionid) 
    LEFT JOIN " . TABLE_PREFIX . "paymentinfo AS paymentinfo 
     ON (paymenttransaction.paymentinfoid = paymentinfo.paymentinfoid) 
    LEFT JOIN " . TABLE_PREFIX . "purchase_temp AS purchase_temp 
     ON (paymentinfo.hash = purchase_temp.hash) $filterlogs_where 
    GROUP BY paymentslog.logid 
    ORDER BY paymentslog.dateline DESC 
    LIMIT $startat, $perpage 
  • 所有这些连接都需要对SELECT访问线程ID除了与用户表的连接来访问用户名,usergroupid和displaygroupid
  • 它需要20秒运行(!),我尝试在解决这个问题,在为列transactionid(表paymentlog)添加INDEX之后,现在需要...... 60秒!
  • 出于某种原因,这是多次返回特定行,基于这个原因,我固定它通过添加一个“GROUP BY paymentslog.logid”

我必须注意的是:
- $ filterlogs_where PHP变量具有查询的WHERE(我通过php为付款日志创建了不同的过滤器)。 默认情况下,$ filterlogs_where的值为“1 = 1”,如果我必须应用过滤器,则添加。=“AND paymentslog.userid = X”等。

任何想法为什么此查询是如此之慢?
我想我已经看过并且写了几秒或几毫秒内运行的更复杂的查询。为什么这个问题与上面的查询?

+0

尽管加入哈希是可能的,但加入整数应该快很多。我们在谈论多少数据,你忽略了告诉我们。 – Xorifelse

+5

加入整数可能会更快一些,但就是这样。如果没有所有相关表的CREATE TABLE语句和针对上述查询的EXPLAIN,不可能帮助解决这个问题 – Strawberry

+0

@Xorifelse - 没有'HASH'索引。无论如何,哈希只比BTree略快。 –

回答

0

首先,我必须告诫你不要有多个具有相同模式的表。这通常是一个糟糕的设计。

你真的需要LEFT?也就是说,即使“右”表没有任何内容,您还是希望返回一行?如果没有,只需使用JOIN

摆脱LEFTs可能会摆脱GROUP BY。加入后跟GROUP BY通常会导致“膨胀行数”,然后是“通过组缩小”。这会在此过程中创建一个巨大的临时表,从而减慢速度。

然后我需要指出Pagination via Offset有问题 - 通常会导致查询时间过长。但是,我们需要摆脱GROUP BY以使此技术成为可能。

请使用较短的别名。

现在,回到您的具体情况......那么,首先工作在上面的东西。并供应SHOW CREATE TABLE。然后像这样的事情会加快速度:

SELECT ... 
    FROM (SELECT id 
       ORDER BY dateline DESC 
       LIMIT $startat, $perpage) AS pl 
    JOIN user ON ... 
    JOIN ... 
    ORDER BY dateline DESC; -- yes, needs repeating 
+0

你好瑞奇,非常感谢你的分析回复!正如我可以理解你的例子,我写了以下查询:http://pastebin.com/GQAWe9AZ这是正确的吗?它似乎有很多记录返回正确的结果,但与2记录的测试,没有人出现。对不起,长的别名,将尽快修复它们。 – user3594130

+0

也许你确实需要'LEFT'。 (我不明白查询的_intent_。) –

+0

好的!查询工作完美,非常感谢你:) – user3594130