简体   繁体   English

查询效率(多项选择)

[英]Query efficiency (multiple selects)

I have two tables - one called customer_records and another called customer_actions . 我有两个表-一个称为customer_records ,另一个称为customer_actions

customer_records has the following schema: customer_records具有以下架构:

CustomerID (auto increment, primary key)
CustomerName
...etc...

customer_actions has the following schema: customer_actions具有以下架构:

ActionID (auto increment, primary key)
CustomerID (relates to customer_records)
ActionType
ActionTime (UNIX time stamp that the entry was made)
Note (TEXT type)

Every time a user carries out an action on a customer record, an entry is made in customer_actions , and the user is given the opportunity to enter a note. 每一个用户执行一个客户记录的动作时,一个条目是由customer_actions ,并给予用户输入一个音符的机会。 ActionType can be one of a few values (like 'designatory update' or 'added case info' - can only be one of a list of options). ActionType可以是几个值之一(例如“指定更新”或“添加的案例信息”-只能是选项列表之一)。

What I want to be able to do is display a list of records from customer_records where the last ActionType was a certain value. 我想要做的是显示一个来自customer_records的记录列表,其中最后一个ActionType是某个值。

So far, I've searched the net/SO and come up with this monster: 到目前为止,我已经搜索了网络/ SO并提出了这个怪物:

SELECT * FROM (
    SELECT * FROM (
        SELECT * FROM `customer_actions` ORDER BY `EntryID` DESC
    ) list1 GROUP BY `CustomerID`
) list2 WHERE `ActionType`='whatever' LIMIT 0,30

Which is great - it lists each customer ID and their last action. 很棒-它列出了每个客户ID及其最后的操作。 But the query is extremely slow on occasions (note: there are nearly 20,000 records in customer_records ). 但是查询有时非常慢(请注意: customer_records有近20,000条记录)。 Can anyone offer any tips on how I can sort this monster of a query out or adjust my table to give faster results? 谁能提供任何提示,说明如何解决查询中的这个怪问题或调整表格以提供更快的结果? I'm using MySQL. 我正在使用MySQL。 Any help is really appreciated, thanks. 非常感谢您的任何帮助。

Edit: To be clear, I need to see a list of customers who's last action was 'whatever'. 编辑:明确地说,我需要查看上一个操作是“无论如何”的客户列表。

To filter customers by their last action, you could use a correlated sub-query... 要按客户的最后操作来过滤客户,您可以使用相关子查询...

SELECT
  *
FROM
  customer_records
INNER JOIN
  customer_actions
    ON  customer_actions.CustomerID = customer_records.CustomerID
    AND customer_actions.ActionDate = (
           SELECT
             MAX(ActionDate)
           FROM
             customer_actions  AS lookup
           WHERE
             CustomerID = customer_records.CustomerID
        )
WHERE
  customer_actions.ActionType = 'Whatever'

You may find it more efficient to avoid the correlated sub-query as follows... 您可能会发现避免关联子查询的效率更高,如下所示...

SELECT
  *
FROM
  customer_records
INNER JOIN
  (SELECT CustomerID, MAX(ActionDate) AS ActionDate FROM customer_actions GROUP BY CustomerID) AS last_action
    ON customer_records.CustomerID = last_action.CustomerID
INNER JOIN
  customer_actions 
    ON  customer_actions.CustomerID = last_action.CustomerID
    AND customer_actions.ActionDate = last_action.ActionDate
WHERE
  customer_actions.ActionType = 'Whatever'

I'm not sure if I understand the requirements but it looks to me like a JOIN would be enough for that. 我不确定我是否理解要求,但是在我看来,JOIN就足够了。

SELECT  cr.CustomerID, cr.CustomerName, ...
FROM    customer_records cr
        INNER JOIN customer_actions ca ON ca.CustomerID = cr.CustomerID
WHERE   `ActionType` = 'whatever'
ORDER BY
        ca.EntryID

Note that 20.000 records should not pose a performance problem 请注意,20.000条记录不应引起性能问题

Please note that I've adapted Lieven's answer (I made a separate post as this was too long for a comment). 请注意,我已经调整了Lieven的答案(我写了一篇单独的文章,因为这太久了,无法发表评论)。 Any credit for the solution itself goes to him, I'm just trying to show you some key points for improving performance. 该解决方案本身值得大家称赞,我只是想向您展示一些提高性能的关键点。

If speed is a concern then the following should give you some suggestions for improving it: 如果需要考虑速度,则以下内容应为您提供一些改进建议:

select top 100 -- Change as required
        cr.CustomerID ,
        cr.CustomerName,
        cr.MoreDetail1,
        cr.Etc
from    customer_records cr
        inner join customer_actions ca 
            on ca.CustomerID = cr.CustomerID
where   ca.ActionType = 'x'
order by cr.CustomerID

A few notes: 一些注意事项:

  • In some cases I find left outer joins to be faster then inner joins - It would be worth measuring performance for both for this query 在某些情况下,我发现左外连接要比内连接快-对于此查询,这两个都应该衡量性能
  • Avoid returning * wherever possible 尽可能避免返回*
  • You don't have to reference 'cr.x' in the initial select but it's a good habit to get into for when you start working on large queries that can have multiple joins in them (this will make a lot of sense once you start doing this 您不必在初始选择中引用“ cr.x”,但是当您开始处理可以包含多个联接的大型查询时,这是一个好习惯(一旦开始,这很有意义)做这个
  • When using joins always join on a primary key 使用联接时, 始终联接主键

Maybe I'm missing something but what's wrong with a simple join and a where clause? 也许我缺少了一些东西,但是简单的join和where子句怎么了?

Select ActionType, ActionTime, Note
FROM Customer_Records CR
INNER JOIN customer_Actions CA 
  ON CR.CustomerID = CA.CustomerID
Where ActionType = 'added case info'

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM