我是MySql和一般数据库的新手。我有一个查询,我通过在线资源和跟踪和错误的片段一起构建。它真的很慢(27秒),我认为它可以优化。也许有人可以帮我解决这个问题。
这是mySQL的数据结构 - 数据库。版本5.1.51-0
|- purchaseID -|- customerID -|- emotionID -|- customerCountryCode -|- customerContinentCode-|
| 1 | 2345 | 0 | US | NA |
| 2 | 2345 | 3 | US | NA |
| 3 | 4456 | 0 | UK | EU |
| 3 | 4456 | 5 | UK | EU |
| 4 | 4456 | 2 | UK | EU |
| 5 | 4456 | 2 | UK | EU |
| 6 | 1234 | 0 | US | NA |
| 7 | 6678 | 0 | US | NA |
| 8 | 9900 | 0 | US | NA |
| 9 | 3334 | 0 | US | NA |
| 10 | 3334 | 4 | US | NA |
数据库用于保存所有已完成的购买。每次购买customerID
,他来自的国家和大陆都会被保存。顾客还可以从一组6种情绪中评价他的购买情况。 (快乐,失望,......)他选择的情绪保存为emotionID
。
所以现在我需要一个查询来获取具有百分比信息的特定emotionID
的前六名客户。假设我找了emotionID = 0
这就是我想得到的:
|- customerID -|- emotionPercent -|
| 1234 | 100 |
| 6678 | 100 |
| 9900 | 100 |
| 2345 | 50 |
| 3334 | 50 |
| 4456 | 25 |
我正在使用此查询:
SELECT customers.customerID, Count( customers.emotionID ) / C.totalPeople * 100.0 AS emotionPercent
FROM `customers`
INNER JOIN
(SELECT customers.customerID, Count( customers.emotionID ) AS totalPeople
FROM `customers`
GROUP BY customerID) C
ON customers.customerID = C.customerID
WHERE customers.emotionID = 0
GROUP BY customers.customerID
ORDER BY emotionPercent DESC
LIMIT 0,6
我已经搜索了答案,但额外的百分比计算让我失望。我找到了一些解决方案,需要填充某种临时表,但我无法使用它。
问题是: 目前,数据库中有140,000个条目,此查询大约需要27秒。这可能是对的吗?使用SQL-Server会显着提高速度吗?
我没有得到的是:要求世界上最幸福的国家快速闪电(0.4秒),但结构上与第一个查询类似(27秒):
SELECT customers.customerCountryCode, Count( customers.emotionID ) / C.totalPeople * 100.0 AS emotionPercent
FROM `customers`
INNER JOIN
(SELECT customers.customerCountryCode, Count( customers.emotionID ) AS totalPeople
FROM `customers`
GROUP BY customerCountryCode) C
ON customers.customerCountryCode = C.customerCountryCode
WHERE customers.emotionID = 0
GROUP BY customers.customerCountryCode
ORDER BY emotionPercent DESC
LIMIT 0,6
当我将此示例中的GROUP BY
的{{1}}更改为INNER Query
时,查询也会永久保留。因此customerID
的分组导致了问题。但为什么呢?
customerID
定义为customerCountryCode
。 varchar(2)
是customerID
。这是否会导致查询性能的巨大差异?是否有更合适的变量类型? int(11)
最多可包含8个数字。
很多问题!感谢阅读和任何帮助!
答案 0 :(得分:0)
首先,如果您认为数据库中的条目会膨胀,或者您的条目很高且服务器速度很慢,恕我直言,您可能需要预处理数据并将其存储到另一个数据库中总结结果,这样,您就不必一遍又一遍地请求相同的过程。另外,尝试为您的应用使用缓存插件。用于php的memcache或j2ee上的ehcache将是安全的投注。
答案 1 :(得分:0)
您的问题可能是您正在使用子查询。由于子查询不使用也不设置索引,因此它们使用最慢的连接方法(即全表扫描)。我没有足够的经验来提供仅限SQL的解决方案,因此我建议您将查询分解为两个单独的调用。
WHERE custumerID IN (id1, id2, id3, etc)
虽然这可能不是最漂亮的解决方案,但您可以避免使用无索引子查询(以及非常慢的全表扫描)。
答案 2 :(得分:0)
感谢您的帮助!
来自mySQL论坛的人建议添加一些索引:
ALTER TABLE customers
ADD KEY idx_country_emid (customerCountryCode, emotionID),
ADD KEY idx_emid_custid (emotionID, customerID);
查询时间从27秒减少到0.1秒。 ;)
此外,对于内部查询,您可以编写
(SELECT customers.customerCountryCode, Count( * ) AS totalPeople
FROM `customers`
GROUP BY customerCountryCode) C