Разделение большого стола по датам - PullRequest
1 голос
/ 13 января 2020

Я внедрил пользовательское сокращение URL в моем приложении, и у меня есть одна таблица для этого. Структура таблицы выглядит следующим образом:

CREATE TABLE `urls` (
  `id` int(11) NOT NULL,
  `url_id` varchar(10) DEFAULT NULL,
  `long_url` varchar(255) DEFAULT NULL,
  `clicked` mediumint(5) NOT NULL DEFAULT 0,
  `user_id` varchar(7) DEFAULT NULL,
  `type` varchar(15) DEFAULT NULL,
  `ad_id` int(11) DEFAULT NULL,
  `campaign` int(11) DEFAULT,
  `increment` tinyint(1) NOT NULL DEFAULT 0,
  `date` date DEFAULT NULL,
  `del` enum('1','0') NOT NULL DEFAULT '0'
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT

ALTER TABLE `urls`
  ADD PRIMARY KEY (`id`),
  ADD KEY `url_id` (`url_id`),
  ADD KEY `type` (`type`),
  ADD KEY `campaign` (`campaign`),
  ADD KEY `ad_id` (`ad_id`),
  ADD KEY `date` (`date`),
  ADD KEY `user_id` (`user_id`);

Таблица теперь содержит 20 000 000 записей и в настоящее время растет на 300–400 000 записей в день.

url_id столбец уникален varchar(10) и URL выглядит так: http://example.com/asdfghjklu

Теперь я разделил эту таблицу на 10 разделов по HASH(id):

PARTITION BY HASH (`id`)
PARTITIONS 10;

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

Когда я пытаюсь сделать большой запрос в этой таблице, я фильтрую почти каждый запрос с датами, и я думаю, что будет гораздо лучше, если я разделю эта таблица по date столбцу. Это хорошая идея?

Когда я читаю, если я хочу разбить эту таблицу по дате, мне нужно добавить дату в составной первичный ключ: PRIMARY KEY(id, date)

Что вы думаете об этом? Как улучшить производительность моего запроса?

1 Ответ

1 голос
/ 13 января 2020

Я рекомендую использовать раздел ha sh с указанием даты или месяца или ГОДА

CREATE TABLE `urls` (
  `id` int(11) NOT NULL,
  `url_id` varchar(10) DEFAULT NULL,
  `long_url` varchar(255) DEFAULT NULL,
  `clicked` mediumint(5) NOT NULL DEFAULT 0,
  `user_id` varchar(7) DEFAULT NULL,
  `type` varchar(15) DEFAULT NULL,
  `ad_id` int(11) DEFAULT NULL,
  `campaign` int(11) DEFAULT,
  `increment` tinyint(1) NOT NULL DEFAULT 0,
  `date` date DEFAULT NULL,
  `del` enum('1','0') NOT NULL DEFAULT '0',
    PartitionsID int(4) unsigned NOT NULL,
   KEY PartitionsID (PartitionsID)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
PARTITION BY HASH (PartitionsID)
PARTITIONS 366;

В идентификаторе PARTITION, вам просто нужно вставить TO_DAYS (дату), чтобы у вас было только одно значение на весь день. ИСТОЧНИК

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

для выбора вы можете использовать ниже запрос как пример

SELECT *    
            FROM TT ACT
            WHERE ACT.CustomerID = vCustomerID 
              AND ACT.TransactionTime BETWEEN vInvoiceEndDate AND vPaymentDueDate 
              AND ACT.TrxnInfoTypeID IN (19, 23) 
              AND ACT.PaymentType = '1'
    AND ACT.PartitionsID BETWEEN TO_DAYS(vInvoiceEndDate) AND TO_DAYS(vPaymentDueDate);
...