Я использую MySQL DB и имею следующую таблицу:
CREATE TABLE SomeTable (
PrimaryKeyCol BIGINT(20) NOT NULL,
A BIGINT(20) NOT NULL,
FirstX INT(11) NOT NULL,
LastX INT(11) NOT NULL,
P INT(11) NOT NULL,
Y INT(11) NOT NULL,
Z INT(11) NOT NULL,
B BIGINT(20) DEFAULT NULL,
PRIMARY KEY (PrimaryKeyCol),
UNIQUE KEY FirstLastXPriority_Index (FirstX,LastX,P)
) ENGINE=InnoDB;
Таблица содержит 4,3 миллиона строк и никогда не изменяется после инициализации.
Важными столбцами этой таблицы являются FirstX
, LastX
, Y
, Z
и P
.
Как вы можете видеть, у меня есть уникальный индекс в строках FirstX
, LastX
и P
.
Столбцы FirstX
и LastX
определяют диапазон целых чисел.
Запрос, который мне нужно запустить в этой таблице, извлекает для данного X все строки, имеющие FirstX <= X <= LastX (то есть все строки, диапазон которых содержит входное число X).
Например, если таблица содержит строки (я включаю только соответствующие столбцы):
FirstX LastX P Y Z
------ ------ - --- ---
100000 500000 1 111 222
150000 220000 2 333 444
180000 190000 3 555 666
550000 660000 4 777 888
700000 900000 5 999 111
750000 850000 6 222 333
и мне нужны, например, строки, содержащие значение 185000
, первые строки 3
должны быть возвращены.
В запросе, который я использовал, который должен использовать индекс, есть:
SELECT P, Y, Z FROM SomeTable WHERE FirstX <= ? AND LastX >= ? LIMIT 10;
Даже без LIMIT этот запрос должен возвращать небольшое количество записей (меньше 50
) для любого заданного X.
Этот запрос был выполнен приложением Java для 120000
значений X. К моему удивлению, он занял 10 часов (!), а среднее время на запрос 0,3 секунды.
Это неприемлемо, даже не приемлемо. Это должно быть намного быстрее.
Я просмотрел один запрос, который потребовал 0,563 секунды, чтобы убедиться, что этот индекс использовался. Запрос, который я попробовал (так же, как запрос выше с конкретным значением целого числа вместо ?
), вернул 2 строки.
Я использовал EXPLAIN
, чтобы узнать, что происходит:
id 1
select_type SIMPLE
table SomeTable
type range
possible_keys FirstLastXPriority_Index
key FirstLastXPriority_Index
key_len 4
ref NULL
rows 2104820
Extra Using index condition
Как вы можете видеть, выполнение включало строки 2104820
(почти 50% строк таблицы), хотя только 2 строки удовлетворяют условиям, поэтому половина индекса проверяется, чтобы вернуть всего 2 строки.
Что-то не так с запросом или индексом? Можете ли вы предложить улучшение запроса или индекса?
EDIT:
В некоторых ответах было предложено, что я запускаю запрос пакетами для нескольких значений X. Я не могу этого сделать, так как я запускаю этот запрос в режиме реального времени, так как входные данные поступают в мое приложение. Каждый раз, когда приходит вход X, я должен выполнить запрос для X и выполнить некоторую обработку на выходе запроса.