как разделить таблицу по столбцу datetime? - PullRequest
13 голосов
/ 23 мая 2011

Я хочу разделить таблицу mysql по столбцу datetime.Однажды раздел. Сценарии создания таблицы выглядят так:

CREATE TABLE raw_log_2011_4 (
  id bigint(20) NOT NULL AUTO_INCREMENT,
  logid char(16) NOT NULL,
  tid char(16) NOT NULL,
  reporterip char(46) DEFAULT NULL,
  ftime datetime DEFAULT NULL,
  KEY id (id)
) ENGINE=InnoDB AUTO_INCREMENT=286802795 DEFAULT CHARSET=utf8
PARTITION BY hash (day(ftime)) partitions 31;

Но когда я выбираю данные за какой-то день. Не удается найти раздел. Оператор выбора выглядит так:

explain partitions select * from raw_log_2011_4 where day(ftime) = 30;

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

explain partitions select * from raw_log_2011_4 where ftime = '2011-03-30';

Кто-нибудь скажет мне, как я могу выбрать данные за один день и сделатьИспользование раздела. Спасибо!

Ответы [ 4 ]

19 голосов
/ 18 октября 2013

Разделение по HASH - очень плохая идея со столбцами даты и времени, потому что он не может использовать сокращение раздела . Из документов MySQL:

Сокращение может использоваться только для целочисленных столбцов таблиц, разделенных ХЭШ или КЛЮЧ. Например, этот запрос к таблице t4 не может использовать сокращение потому что dob является столбцом DATE:

SELECT * FROM t4 WHERE dob >= '2001-04-14' AND dob <= '2005-10-15';

Однако, если таблица хранит значения года в столбце INT, тогда запрос с ГДЕ year_col> = 2001 И year_col <= 2005 может быть обрезка. </p>

Таким образом, вы можете сохранить значение TO_DAYS (DATE ()) в дополнительном столбце INTEGER для использования сокращения.

Другой вариант - использовать RANGE-разбиение:

CREATE TABLE raw_log_2011_4 (
  id bigint(20) NOT NULL AUTO_INCREMENT,
  logid char(16) NOT NULL,
  tid char(16) NOT NULL,
  reporterip char(46) DEFAULT NULL,
  ftime datetime DEFAULT NULL,
  KEY id (id)
) ENGINE=InnoDB AUTO_INCREMENT=286802795 DEFAULT CHARSET=utf8
  PARTITION BY RANGE( TO_DAYS(ftime) ) (
    PARTITION p20110401 VALUES LESS THAN (TO_DAYS('2011-04-02')),
    PARTITION p20110402 VALUES LESS THAN (TO_DAYS('2011-04-03')),
    PARTITION p20110403 VALUES LESS THAN (TO_DAYS('2011-04-04')),
    PARTITION p20110404 VALUES LESS THAN (TO_DAYS('2011-04-05')),
    ...
    PARTITION p20110426 VALUES LESS THAN (TO_DAYS('2011-04-27')),
    PARTITION p20110427 VALUES LESS THAN (TO_DAYS('2011-04-28')),
    PARTITION p20110428 VALUES LESS THAN (TO_DAYS('2011-04-29')),
    PARTITION p20110429 VALUES LESS THAN (TO_DAYS('2011-04-30')),
    PARTITION future VALUES LESS THAN MAXVALUE
  );

Теперь в следующем запросе будет использоваться только раздел p20110403:

SELECT * FROM raw_log_2011_4 WHERE ftime = '2011-04-03';
9 голосов
/ 28 мая 2011

Привет. Вы делаете неправильный раздел в определении таблицы, определение таблицы будет выглядеть так:

CREATE TABLE raw_log_2011_4 (
  id bigint(20) NOT NULL AUTO_INCREMENT,
  logid char(16) NOT NULL,
  tid char(16) NOT NULL,
  reporterip char(46) DEFAULT NULL,
  ftime datetime DEFAULT NULL,
  KEY id (id)
) ENGINE=InnoDB AUTO_INCREMENT=286802795 DEFAULT CHARSET=utf8
PARTITION BY hash (TO_DAYS(ftime)) partitions 31;

И ваша команда выбора будет:

explain partitions 
    select * from raw_log_2011_4 where TO_DAYS(ftime) = '2011-03-30';

Приведенная выше команда выберет все необходимые даты, как если бы вы использовали команду TO_DAYS в качестве

mysql> SELECT TO_DAYS(950501);
        -> 728779
mysql> SELECT TO_DAYS('2007-10-07');
        -> 733321

Зачем использовать TO_DAYS AS Оптимизатор MySQL распознает две функции на основе даты для сокращения разделов: 1.TO_DAYS () 2.YEAR ()

и это решит вашу проблему ..

1 голос
/ 26 октября 2011

Я только что прочитал сообщение в блоге MySQL, касающееся этого, на http://dev.mysql.com/tech-resources/articles/mysql_55_partitioning.html.

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

Версии 5.5 и более поздние позволяли выполнять прямое разбиение с использованием нечисловых значений, таких как даты и строки.

0 голосов
/ 26 ноября 2015

Не используйте CHAR, используйте VARCHAR.Это сэкономит много места, а следовательно, уменьшит количество операций ввода-вывода и, следовательно, ускорит запросы.

reporterip: (46) неоправданно велико для IP-адреса, даже IPv6.См. Мой блог для дальнейшего обсуждения, в том числе о том, как уменьшить его до 16 байт.

PARTITION BY RANGE(TO_DAYS(...)), как предложил @Steyx, но не более 50 разделов.Чем больше у вас разделов, тем медленнее получаются запросы, несмотря на «сокращение».HASH разбиение по существу бесполезно.

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

...