2015-02-07 3 views
-1

Я хранил всю транзакцию по сделке каждого торгового дня в таблице. Таблица содержит миллионы строк. Поскольку в то же время и во втором случае может произойти 2 или более транзакций, а исходные данные также не имеют первичного ключа. поэтому я не добавил первичный ключ к таблице. Но выполнение любого запроса происходит очень медленно, около 60 - 120 секунд.Как ускорить скорость запросов SQL

Вот структура: MySQL, InnoDB, utf8_general_ci

Ticker varchar(15) 
ReleaseDT datetime 
Order int(1) 
Price decimal (7,3) 
Volume bigint(13) 
Amount bigint(13) 
NoOfLot int(11) 
Session varchar(3) 
Source varchar(15) 
TimeStamp timestamp 

функция:

  1. получить каждый объем тикер по цене в день или в течение определенного периода времени.
  2. , чтобы узнать, сколько всего общей суммы покупки и общей продажи тикера каждый день
  3. далее по пункту 2, я разделить его на утреннюю общую сумму покупки и утро.

Вопрос: 1. Поскольку нет уникального элемента, который я мог бы найти, не будет ли первичный ключ для этой таблицы влиять на скорость запроса?

  1. Должен ли я просто добавить auto_incremental # like ID, и он создает себя? помогает ли она в скорости запросов?

  2. Некоторые запросы, которые мне нужны 60-120 секунд, чтобы улучшить приведенную выше таблицу? как индекс? если да, то пожалуйста сообщите как.

Я буду использовать php для веб-запроса и вывода, а иногда и vb.net для запроса с сервера mysql.

пример:

select Ticker, ReleaseDT as 'Last Update',Price, convert(sum(case when iOrder = 1 then Amount else 0 end),decimal(9,0)) as TtlBuyAmt, 
convert(sum(case when iOrder = -1 then Amount else 0 end),decimal(9,0)) as TTlSellAmt, 
convert(sum(case when iOrder = 0 then Amount else 0 end),decimal(9,0)) as TTlUndetAmt, 
convert(sum(case when iOrder = 1 then Amount else 0 end)/sum(case when iOrder = -1 then Amount else 0 end),decimal(9,0)) as TTlBuySellRatio, 
sum(case when iOrder = 1 and Session = 'AM' then Amount else 0 end) as BuyAmtAM , 
SUM(CASE WHEN iOrder = 1 and Session = 'PM' then Amount else 0 end) as BuyAmtPM , 
SUM(CASE WHEN iOrder = -1 and Session = 'AM' then Amount else 0 end) as SellAmtAM, 
SUM(CASE WHEN iOrder = -1 and Session = 'PM' then Amount else 0 end) as SellAmtPM , 
convert(SUM(CASE WHEN iOrder = -1 and Session = 'PM' then Amount else 0 end)/SUM(CASE WHEN iOrder = -1 and Session = 'AM' then Amount else 0 end),decimal(5,2)) as SellPMAMRatio, 
sum(Amount) as TotalAmt, 
convert(sum(case when iOrder = 1 then Amount else 0 end) - sum(case when iOrder = -1 then Amount else 0 end),decimal(9,0)) as NetAmount 
FROM Trade 
WHERE Ticker = '1 HK EQUITY' and DATE(ReleaseDT) between '20150102' and '20150104' 
GROUP BY Ticker, date(ReleaseDT), Price 
ORDER BY Ticker ASC, Price DESC 

Это занимает> 60secs бежать, любой способ улучшить?

SELECT * FROM AS2046.BlockTrade_EOD where Ticker = '1 HK EQUITY' and Date(ReleaseDT) > '20150102' Group by Price 

с помощью EXPLAIN ... и результаты следующим образом:

# id, select_type, table, type, possible_keys, key, key_len, ref, rows, Extra 
'1', 'SIMPLE', 'BlockTrade_EOD', 'ALL', NULL, NULL, NULL, NULL, '2327212', 'Using where; Using temporary; Using filesort' 
+1

Пожалуйста, сделайте 'EXPLAIN SELECT [...]' своим запросом и опубликуйте результат в своем вопросе. Также, пожалуйста, отправьте полное 'CREATE TABLE' -statement из соответствующих таблиц. – Bjoern

+0

Добро пожаловать в Переполнение стека. Несомненно, что индексы помогут вашим запросам в этой таблице. Для нас, чтобы помочь вам, нам нужно увидеть некоторые из медленных запросов. Измените свой вопрос, чтобы включить их.В то же время читайте о ** составных индексах покрытия, **. –

+0

. Это один из часто используемых sql-запросов. – Trader

ответ

0

, так как это все еще довольно широкий вопрос с очень ограниченным входом, я попытаюсь дать некоторые ограниченные рекомендации:

  1. Первичный ключ не обязательно ускорит запросы. Это во многом зависит от ваших запросов. Зачастую индексы (не обязательно первичные ключи). Из запроса, который вы опубликовали, кажется, существует вероятность того, что индекс по тикеру (а не первичный ключ, поскольку Тикер не уникален, по-видимому) может ускорить операции («ГДЕ Tickler = '...' "). Также ReleaseDT является кандидатом на индекс - возможно, вместе с Тикером. Но все это зависит от данных в вашей таблице ... например: Сколько из строк имеет значение Ticker «1 HK EQUITY».

  2. Очень маловероятно, что добавит искусственную операцию ускорения ПК. Многие базы данных добавляют искусственный ПК самостоятельно. Также я не вижу, как искусственный ПК может помочь в этом выборе. Конечно, первичный ключ может быть полезен в других вариантах.

  3. См. 1. Мое лучшее предположение - это тикер и/или ReleaseDT для индекса (или даже ПК в зависимости от ваших данных).То, что вы видите, скорее всего, «полное сканирование таблицы» - механизм базы данных должен обрабатывать все ваши миллионы строк для одного SELECT. Индекс может значительно сократить операции - в зависимости от ваших данных в базе данных.

Я рекомендовал бы проверить содержимое вашей таблицы (например, сколько строк содержат «1 HK СПРАВЕДЛИВОСТИ» как Ticker. Если только часть строк сделать так, начните добавлять индекс по этой строке.

Но:.! Осторожно - каждый индекс таблицы добавит сложности для всех записей в таблице, так как индекс должен поддерживаться

для получения дальнейших рекомендаций, больше данных будет необходимо

1

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

Для вашего запроса, композитный индекс должен помочь:

create index idx_Trade_ReleaseDT on Trade(Ticker, ReleaseDT) 

Однако, вам нужно исправить положение where. Если ReleaseDt не имеет компонент времени, а затем использовать:

WHERE Ticker = '1 HK EQUITY' and 
     ReleaseDT between DATE('2015-01-02') and DATE('2015-01-04') 

Или, если ReleaseDT может иметь временную составляющую:

WHERE Ticker = '1 HK EQUITY' and 
     ReleaseDT >= DATE('2015-01-02') and 
     ReleaseDT < DATE('2015-01-05') 
+0

Спасибо в первую очередь. Я потерял соединение во время создания индекса. Кроме того, я использую Date (ReleaseDT) между '20150102' и '20150104', которые будут использоваться в той же цели, что и вы. – Trader

+1

@Trader. , , Я не думаю, что конструкция будет использовать индекс. Обычно вам нужны «голые» столбцы, чтобы двигатель использовал индекс. –

0

Первое, должно быть ReleaseDT DATETIME, а не только DATE? Предполагая, что есть компонент TIME ...

Если стол InnoDB, у вас действительно должен иметь явный ПЕРВЫЙ КЛЮЧ. (Если это MyISAM, это не имеет значения. (Пожалуйста, предоставьте SHOW CREATE TABLE)

Добавить составной индекс INDEX(Ticker, ReleaseDT). И не скрывать столбцы внутри функций, таких, как DATE(ReleaseDT). Это делает невозможным использование индекса . Как говорит @Gordon, но еще проще:

ReleaseDT >= '2015-01-02' and 
ReleaseDT < '2015-01-05' 

Я предпочитаю это, если я знаю, сколько дней и не хочу играть даты арифметика:

ReleaseDT >= '2015-01-02' and 
ReleaseDT < '2015-01-02' + INTERVAL 3 DAY 

Никаких изменений не требуются в

GROUP BY Ticker, date(ReleaseDT), Price 

Возможно

convert(sum(case when iOrder = -1 then Amount else 0 end),decimal(9,0)) 

может быть упрощено до

SUM(IF(iOrder = -1, Amount, 0)) 

Если ReleaseDT может быть ДАТА, то PRIMARY KEY (Ticker, ReleaseDT), вероятно, лучше.

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