Объединение нескольких таблиц делает запрос слишком длинным - PullRequest
0 голосов
/ 25 ноября 2011

У меня есть несколько таблиц, содержащих (a.o.) следующие поля:

tweets:
--------------------------
tweet_id ticker created_at
--------------------------
1        1      1298063318
2        1      1298053197

stocks:
---------------------------------
ticker date        close volume
---------------------------------
1      1313013600  12.25 40370600
1      1312927200  11.60 37281300

wiki:
-----------------------
ticker date       views
-----------------------
1      1296514800   550
1      1296601200   504

Я хочу составить обзор количества твитов, закрытия, объема и просмотров за день (для строк, обозначенных тикером = 1). Таблица твитов является ведущей, это означает, что если есть дата, когда нет твитов, закрытие, объем и просмотры для этого дня не имеют значения. Другими словами, я хочу, чтобы результат запроса был таким:

-------------------------------------
date        tweets close volume views
-------------------------------------
2011-02-13  4533   12.25 40370600 550
2011-02-14  6534   11.60 53543564 340
2011-02-16  5333   13.10 56464333 664

В выходных данных этого примера не было твитов 2011-02-15, поэтому нет необходимости в остальных данных за этот день. Пока что мой запрос:

SELECT 
  DATE_FORMAT(FROM_UNIXTIME(tweets.created_at), '%Y-%m-%d') AS date, 
  COUNT(tweets.tweet_id) AS tweets,
  stocks.close,
  stocks.volume,
  wiki.views
FROM tweets
LEFT JOIN stocks ON tweets.ticker = stocks.ticker
LEFT JOIN wiki ON tweets.ticker = wiki.ticker
WHERE tweets.ticker = 1
GROUP BY date
ORDER BY date ASC

Может ли кто-нибудь проверить правильность этого запроса? Он не сталкивается ни с какими ошибками, но замораживает мой компьютер. Возможно, я должен установить индекс здесь или там, возможно, в столбцах "тикер"?

[править]

По запросу, определения таблицы:

CREATE TABLE `stocks` (
  `ticker` int(3) NOT NULL,
  `date` int(10) NOT NULL,
  `open` decimal(8,2) NOT NULL,
  `high` decimal(8,2) NOT NULL,
  `low` decimal(8,2) NOT NULL,
  `close` decimal(8,2) NOT NULL,
  `volume` int(8) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

CREATE TABLE `tweets` (
  `tweet_id` int(11) NOT NULL AUTO_INCREMENT,
  `ticker` varchar(5) NOT NULL,
  `id_str` varchar(18) NOT NULL,
  `created_at` int(10) NOT NULL,
  `from_user` int(11) NOT NULL,
  `text` text NOT NULL,
  PRIMARY KEY (`tweet_id`),
  KEY `id_str` (`id_str`),
  KEY `from_user` (`from_user`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1;

CREATE TABLE `wiki` (
  `ticker` int(3) NOT NULL,
  `date` int(11) NOT NULL,
  `views` int(6) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

Надеюсь, это поможет.

Ответы [ 3 ]

2 голосов
/ 25 ноября 2011

Вы правы в отношении индексов, без индекса на тикере вам придется выполнять поиск по всем таблицам, и если они большие, это займет много времени.

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

Проверьте запросы с помощью [EXPLAIN SELECT ...][2], если вы находите их медленными, узнайте, как интерпретировать результаты (не просто, но важно), чтобы понять, куда ставить новые индексы.

1 голос
/ 25 ноября 2011

Неужели вы должны проверить соединения между таблицами?Ваш запрос не указывает, какие строки запасов (или строки вики) должны быть сопоставлены с датой твитов.На основании данных примера сопоставление выполняется для всех акций и вики-строк, имеющих одинаковый идентификатор ticker_id.

Есть ли в акциях и вики-таблицах только одна строка на определенный день для одного тикера?Если предположить, что это так, то более логичный запрос будет выглядеть следующим образом:

SELECT 
  DATE_FORMAT(FROM_UNIXTIME(t.created_at), '%Y-%m-%d') AS date, 
  COUNT(t.tweet_id) AS tweets,
  s.close,
  s.volume,
  w.views
FROM tweets t
  LEFT JOIN stocks s ON t.ticker = s.ticker 
       and FROM_UNIXTIME(t.created_at,'%Y-%m-%d')=FROM_UNIXTIME(s.date,'%Y-%m-%d')
  LEFT JOIN wiki w ON t.ticker = w.ticker
       and FROM_UNIXTIME(t.created_at,'%Y-%m-%d')=FROM_UNIXTIME(w.date,'%Y-%m-%d')
WHERE tweets.ticker = 1
GROUP BY date, s.close, s.volume, w.views
ORDER BY date ASC

Если в акции / вики более одного ряда на определенный день для одного тикера, вам нужно применить статистическую функцию к этимстолбцы и измените COUNT (t.tweet_id) на COUNT (отличный t.created_at).

1 голос
/ 25 ноября 2011

Я думаю, что одной из проблем является расчет даты

DATE_FORMAT(FROM_UNIXTIME(tweets.created_at), '%Y-%m-%d') date

Попробуйте добавить это поле в таблицу твитов, чтобы избежать загрузки процессора

редактировать: Вы можете использовать что-то вроде этого

CREATE TABLE `stocks` (
  `ticker` int(3) NOT NULL,
  `date` int(10) NOT NULL,
  `open` decimal(8,2) NOT NULL,
  `high` decimal(8,2) NOT NULL,
  `low` decimal(8,2) NOT NULL,
  `close` decimal(8,2) NOT NULL,
  `volume` int(8) NOT NULL,
  `day_date` varchar(10) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

CREATE TABLE `tweets` (
  `tweet_id` int(11) NOT NULL AUTO_INCREMENT,
  `ticker` varchar(5) NOT NULL,
  `id_str` varchar(18) NOT NULL,
  `created_at` int(10) NOT NULL,
  `from_user` int(11) NOT NULL,
  `text` text NOT NULL,
  `day_date` varchar(10) NOT NULL,
  PRIMARY KEY (`tweet_id`),
  KEY `id_str` (`id_str`),
  KEY `from_user` (`from_user`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1;

CREATE TABLE `wiki` (
  `ticker` int(3) NOT NULL,
  `date` int(11) NOT NULL,
  `views` int(6) NOT NULL,
  `day_date` varchar(10) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1;


SELECT 
tweets.day_date AS date, 
COUNT(tweets.tweet_id) AS tweets,
stocks.close as close,
stocks.volume as volume,
wiki.views as views
FROM tweets
LEFT JOIN stocks ON tweets.ticker = stocks.ticker 
                and tweets.day_date = stocks.day_date
LEFT JOIN wiki ON tweets.ticker = wiki.ticker
              and tweets.day_date = wiki.day_date
WHERE tweets.ticker = 1
GROUP BY date, close, volume, views
ORDER BY date ASC
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...