Проблемы составного ключа базы данных mysql - PullRequest
0 голосов
/ 09 ноября 2018

У нас есть база данных с таблицей данных, определенной следующим образом:

CREATE TABLE data
(
msts BIGINT,
variable_id INT,
p_id INT,
value DOUBLE,
PRIMARY KEY(msts,variable_id,p_id)
);

ALTER TABLE data
ADD    FOREIGN KEY (p_id)
REFERENCES p(id);

ALTER TABLE data
ADD    FOREIGN KEY (variable_id)
REFERENCES variables(id);

Эта таблица может содержать миллиарды записей.

При выполнении простого запроса:

SELECT COUNT(msts) from data FORCE INDEX(PRIMARY) where (
msts<1535886000000000000 AND msts>1535796060000000000  AND  
variable_id=107  AND p_id=661 );

yeilding:

+-------------+
| COUNT(msts) |
+-------------+
|       89873 |
+-------------+
1 row in set (42.51 sec)

занимает 42,51 секунды для подсчета 89873.

Почему это такдолго видеть, как первичный ключ должен действовать как составной индекс?

Это объяснение:

EXPLAIN SELECT COUNT(msts) from data FORCE INDEX(PRIMARY) where 
( msts<1535886000000000000 AND msts>1535796060000000000  AND 
variable_id=107  AND plant_id=661 );

, которое дает:

rows = 190996998
filtered=0
ref=NULL
type=range

Любая помощь будет многооценили!

1 Ответ

0 голосов
/ 09 ноября 2018

Ваш запрос, переписанный для изменения порядка предложений where, является следующим:

SELECT COUNT(msts) 
  from data 
 where variable_id=107 
   and p_id=661
   and msts>1535796060000000000
   and msts<1535886000000000000;

Содержит два совпадения равенства: variable_id и p_id. Затем он содержит фильтр диапазона по msts. Следовательно, для быстрого удовлетворения вашего запроса вам необходим индекс по (variable_id, p_id, msts) столбцам в таком порядке .

Почему? Вы можете думать об индексах MySQL как отсортированных по порядку. Чтобы удовлетворить ваш запрос, MySQL произвольно обращается к индексу к первому подходящему элементу. Затем он сканирует его последовательно до последнего элемента. Это называется сканированием диапазона индекса.

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

Pro tip 1: Используйте COUNT(*), когда можете вместо COUNT(column). Второй медленнее, потому что он должен опускать любые значения столбца, которые являются NULL. Первый просто считает их всех.

Pro tip 2: Дополнительные индексы из одного столбца бесполезны, если они не помогают ускорить конкретный запрос.

Pro tip 3: Принудительное использование индекса почти всегда является плохим выбором.

Pro tip 4: Read https://use -the-index-luke.com /

Редактировать : Вы спросили, как выполнить преобразование.

Если ваша таблица еще не содержит много миллионов строк, просто измените определение первичного ключа следующим образом.

ALTER TABLE data 
       DROP PRIMARY KEY, 
       ADD PRIMARY KEY (variable_id, p_id, msts);

Если он уже содержит миллиарды строк, вам, вероятно, следует создать новую таблицу с правильным определением, в которую можно скопировать существующую таблицу. Затем скопируйте ваши данные. Затем переименуйте старую таблицу в data_old или что-то еще, и переименуйте новую таблицу в data. Это может быть сложной задачей, включающей пакеты данных; если вы не можете понять это, задайте другой вопрос.

...