MYSQL Оптимизация разницы в значениях - PullRequest
0 голосов
/ 03 августа 2011

Привет, ребята,

Я использую очень большую базу данных (например, ATM> 5 миллионов наборов данных). Моя база данных хранит сгенерированные пользователем числа (которые и как они сочиняют здесь не имеют значения) и соответствующую дату для этого. Кроме того, для каждого продукта хранится идентификатор (означает, что один продукт может иметь несколько записей на разные даты в моей базе данных -> первичный ключ разделен). Теперь я хочу SELECT те 10 лучших идентификаторов, которые получили наибольшую разницу в количестве номеров за последние два дня. В настоящее время я пытался добиться этого с помощью JOINS, но поскольку я получил так много наборов данных, этот путь далек от замедления. Как я мог ускорить всю операцию?

SELECT 
  d1.place,d2.place,d1.ID 
FROM 
  daily 
INNER JOIN 
  daily AS d1 ON d1.date = CURDATE() 
INNER JOIN 
  daily as d2 ON d2.date = DATE_ADD(CURDATE(), INTERVAL -1 DAY) 
ORDER BY 
  d2.code-d1.code LIMIT 10

РЕДАКТИРОВАТЬ: Вот так выглядит моя структура

CREATE TABLE IF NOT EXISTS `daily` (
 `ID` bigint(40) NOT NULL,
 `source` char(20) NOT NULL,
 `date` date NOT NULL,
 `code` int(11) NOT NULL,
 `cc` char(2) NOT NULL,
 PRIMARY KEY (`ID`,`source`,`date`,`cc`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

То есть вывод оператора Explain

    id  select_type table   type    possible_keys   key key_len ref rows    Extra
1   SIMPLE  d1  ALL PRIMARY NULL    NULL    NULL    5150350 Using where; Using temporary; Using filesort
1   SIMPLE  d2  ref PRIMARY PRIMARY 8   mytable.d1.ID   52  Using where

1 Ответ

1 голос
/ 03 августа 2011

Как насчет этого?

SELECT
  d1.ID, d1.place, d2.place
FROM
  daily AS d1
CROSS JOIN
  daily AS d2
USING (ID)
WHERE
  d1.date = CURDATE()
  AND d2.date = CURDATE() - INTERVAL 1 DAY
ORDER BY
  d2.code - d1.code DESC
LIMIT
  10

Некоторые мысли о структуре вашей таблицы.

`ID` bigint(40) NOT NULL,

Почему BIGINT?Вам нужно будет делать 136 вставок / с 24 часа в сутки, 7 дней в неделю в течение года, чтобы исчерпать диапазон INT.И прежде чем вы доберетесь до середины, вашему приложению, вероятно, все равно понадобится профессиональный администратор баз данных.Помните, что меньший первичный индекс ведет к более тщательному поиску - что приводит нас к:

PRIMARY KEY (`ID`,`source`,`date`,`cc`)

Почему?Достаточно одного столбца PK на столбце ID.Если вам нужны индексы для других столбцов, создайте дополнительные индексы (и к этому разумно).На самом деле, у вас есть индекс покрытия для всей таблицы ... как если бы в индексе была вся таблица.

Последнее, но не менее важное: где находится столбец place?Вы использовали его в своем запросе (а затем я в моем), но его нигде не видно?

Предлагаемая структура таблицы:

CREATE TABLE IF NOT EXISTS `daily` (
 `ID` int(10) UNSIGNED NOT NULL,  --usually AUTO_INCREMENT is used as well,
 `source` char(20) NOT NULL,
 `date` date NOT NULL,
 `code` int(11) NOT NULL,
 `cc` char(2) NOT NULL,
 PRIMARY KEY (`ID`),
 KEY `ID_date` (`ID`,`date`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
...