2017-01-28 2 views
1

Я некоторые запросы, которые принимают в течение 30mins казнить, я не эксперт базы данных, так что я действительно не знаю, что так вот, мне нужен кто-то, чтобы предложить лучший запрос для:Оптимизация MySQL отчетов Query

select count(*),substring(tdate,1,7) 
from bills 
where amt='30' 
group by substring(tdate,1,7) 
order by substring(tdate,1,7) desc 

SELECT count(*) 
FROM `bills` 
where amt='30' 
and date(tdate)=date('$date') 
and stat='RENEW' 
and x1 in (select `id` from sub); 

здесь я передать значение даты $ в следующем формате 'Ymd 00:00:00'

select count(*),substring(tdate,1,7) 
from bills 
where amt='30' 
group by substring(tdate,1,7) 
order by substring(tdate,1,7) desc 

Таблица структуры:

MariaDB [talksport]> desc bills; 
+-------+--------------+------+-----+---------+----------------+ 
| Field | Type   | Null | Key | Default | Extra   | 
+-------+--------------+------+-----+---------+----------------+ 
| bid | int(11)  | NO | PRI | NULL | auto_increment | 
| num | varchar(500) | NO |  | NULL |    | 
| stat | varchar(500) | NO |  | NULL |    | 
| tdate | varchar(500) | NO |  | NULL |    | 
| x1 | varchar(500) | NO |  | NULL |    | 
| amt | varchar(500) | NO |  | 30  |    | 
+-------+--------------+------+-----+---------+----------------+ 

Любая помощь приветствуется.

Майкл

+1

Почему вы храните что-то под названием 'tdate' в строке? Аналогично для того, что называется 'amt'? –

+0

, который является датой транзакции, датой и временем, в которые была вставлена ​​запись в таблицу –

+0

Вставить в счета (num, stat, tdate, x1, amt) значения ('1234', 'RENEW', now(), '080777' , '10mt' –

ответ

1

Ваши три запроса действительно два (первый и третий одни и те же). Это ваши три запроса (переформатирован так, что они читаемы):

select count(*), left(tdate, 7) 
from bills 
where amt = '30' 
group by left(tdate, 7) 
order by left(tdate, 7) desc; 

select count(*) 
from `bills` 
where amt = '30' and date(tdate) = date('$date') and stat = 'RENEW' and 
     x1 in (select `id` from sub); 

Во-первых, вы хотите индекс на bills(amt, tdate) для первого запроса. Вторая проблема более проблематична. В некоторых версиях MySQL может возникнуть проблема in. Кроме того, арифметика даты является проблематичной. Итак, если вы храните tdate в качестве ГГГГ-ММ-ДД, тогда перейдите в $date в том же формате (еще лучше, используйте параметры, лучше, но используйте правильные типы). Итак, я хотел бы написать это как:

select count(*) 
from `bills` b 
where amt = '30' and tdate = '$date' and stat = 'RENEW' and 
     exists (select 1 from sub s where b.x1 = s.id); 

Затем вы хотите индекс на bills(amt, stat, tdate, id).

Правильные индексы должны ускорять ваши запросы.

+0

спасибо, я попробую это –

0

В дополнение к ответу выше, можно сделать еще одну оптимизацию, заменяя COUNT(*) на COUNT(id).

Когда вы подсчет всех строк, а каждая строка имеет уникальный идентификатор (id будучи PRIMARY KEY, который уже проиндексирован), вы бы также получить те же COUNT если вы только подсчитываете идентификаторы. Запрос будет искать меньшее количество столбцов, а также тот, который будет просеиваться, уже будет проиндексирован, чтобы ускорить поиск и агрегирование.

Всегда полезно использовать имена конкретных столбцов вместо * в SELECT запросах. Аналогично, всегда просматривайте столбцы, используемые в SELECT, а также столбцы, участвующие в статьях WHERE и GROUP BY, чтобы определить потенциальных кандидатов для индексирования.


Пожалуйста, обратите внимание:
Создание нескольких индексов не следует считать единственным методом оптимизации, так как это может возможно замедлить Bulk INSERT S/UPDATE с, при попытке ускорить SELECT значительно. Кроме того, вы можете создать индексы, которые могут оказаться излишними или избыточными. Поэтому для достижения оптимального баланса необходимо учитывать целостный взгляд на цель приложения - в зависимости от того, сосредоточено ли больше операций пользователя на INSERT/UPDATE или SELECT.

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