2013-12-03 4 views
0
Name Type    Collation Null Default  
1  sms_id   int(7)  None AUTO_INCREMENT 
2  users_id   int(5)  NULL NULL  
3  sms_number  varchar(9) No  None   
4  sms_amount  varchar(7) No  None   
6  server_id   tinyint(2) Yes  NULL   
7  sms_device  varchar(1) No  None   
8  special_id  int(6)  Yes  NULL   
9  sms_ip   varchar(32) No  None   
10 sms_adddate  timestamp No  CURRENT_TIMESTAMP 

У меня есть эта таблица, что запись смс, отправленное с моего сайта я хочу, чтобы вычислить некоторые данные, такие как количество отправленных смс и сумму количества этого смс между два датой для каждого пользователь, но когда я выполнить мой запрос потребовалось много времени, чтобы сделали форму 20-30 секунд, потому что у меня есть миллионы записейMySQL запросы повышенная производительность зависит от даты

это мой MySQL запрос

select *, 
(select count(sms_id) from sms where sms_adddate>11-11-2012 and sms_adddate<11-11-2013 and sms.users_id=users.users_id limit 1) as sms_count, 
(select sum(sms_amount) from sms where 
sms_adddate>11-11-2012 and sms_adddate<11-11-2013 and 
sms.users_id=users.users_id limit 1) as sms_amount 
from users limit 10 

первичный ключ: sms_id внешнего ключа: users_id, server_id, spicial_id

все мои таблицы - это движок InnoDB, и у меня уже есть отношения между ним.

Что я могу сделать, чтобы ускорить этот запрос? Неправильно добавить индекс в sms_amount и sms_adddate или что?

+0

индексов должны быть на столбах, которые вы используете для поиска записей ... те, которые появляются в той части. поэтому, для sms_adddate, да, это хорошая идея –

+0

какие индексы могут делать .. и если хорошо добавить в два столбца, могу ли я сделать это отдельно или вместе. Я имею в виду для каждого столбца, я делаю это или все вместе в тот же index @ naveed-hasan – hazem

+0

@hazem Судя по этому запросу, похоже, что вам нужен индекс с несколькими столбцами через 'sms_adddate' и' user_id' –

ответ

0

У вас есть два подзапроса в вашем запросе, поэтому вы дважды проходите список sms. Попробуйте с этим, я думаю, что он должен взять на себя половину времени:

SELECT users.*, 
     COUNT(DISTINCT sms.sms_id) AS sms_count, 
     SUM(sms.sms_amount) AS sms_amount 
FROM users 
    INNER JOIN sms 
     ON users.users_id = sms.users_id 
     AND sms.sms_adddate>11-11-2012 and sms.sms_adddate<11-11-2013 
WHERE 1 
GROUP BY users.users_id 
# Optionally (extra time consumption): ORDER BY sms_count DESC 
LIMIT 10; 

Кроме того, поля sms.sms_adddate и sms.users_id Шоудом имеет свои индексы, чтобы ускорить фильтры, используемые в запросе.

Вы можете использовать LEFT OUTER JOIN вместо INNER JOIN, если вы хотите видеть пользователь без смс в этот период ... (все пользователи действительно)

+0

i Я скопировал ваш запрос, но это заняло гораздо больше времени, чем мой запрос. – hazem

+0

Вы добавили индекс sms_adddate? Важно (Edit: Также sms.users_id тоже должен иметь индекс) – juanra

+1

Здесь вы можете использовать sms_adddate BETWEEN. Это было бы более читаемо. –

Смежные вопросы