Как я могу ускорить этот запрос SQL на MySQL 4.1? - PullRequest
0 голосов
/ 14 января 2009

У меня есть SQL-запрос, который очень долго выполняется на MySQL (это занимает несколько минут). Запрос выполняется к таблице с более чем 100 миллионами строк, поэтому я не удивлен, что он медленный. В теории, однако, должна быть возможность ускорить его, поскольку я действительно хочу получить только те строки из большой таблицы (назовем это A), которые имеют ссылку в другой таблице, B.

Итак, мой запрос:

SELECT id FROM A, B where A.ref = B.ref;

(у A более 100 миллионов строк; у B всего несколько тысяч).

Я добавил ИНДЕКСЫ:

alter table A add index(ref);
alter table B add index(ref);

Но это все еще очень медленно (несколько минут - я был бы счастлив с одной минутой).

К сожалению, я застрял с MySQL 4.1.22, поэтому не могу использовать представления.

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

Любые предложения приветствуются!

РЕДАКТИРОВАТЬ: Вот результат выполнения EXPLAIN для моего запроса:

+----+-------------+------------------------+------+------------------------------------------+-------------------------+---------+------------------------------------------------+-------+-------------+
| id | select_type | table                  | type | possible_keys                            | key                     | key_len | ref                                            | rows  | Extra       |
+----+-------------+------------------------+------+------------------------------------------+-------------------------+---------+------------------------------------------------+-------+-------------+
|  1 | SIMPLE      | B                      | ALL  | B_ref,ref                                | NULL                    |    NULL | NULL                                           | 16718 | Using where |
|  1 | SIMPLE      | A                      | ref  | A_REF,ref                                | A_ref                   |       4 | DATABASE.B.ref                                 |  5655 |             |
+----+-------------+------------------------+------+------------------------------------------+-------------------------+---------+------------------------------------------------+-------+-------------+

(При редактировании моего исходного примера запроса я решил использовать «ref» в качестве имени столбца, которое совпадает с одним из типов, но, надеюсь, это не слишком смущает ...)

Ответы [ 3 ]

2 голосов
/ 14 января 2009

Оптимизатор запросов, вероятно, уже делает все возможное, но в маловероятном случае, когда он сначала читает гигантскую таблицу (A), вы можете явно указать ему сначала прочитать B, используя синтаксис STRAIGHT_JOIN:

SELECT STRAIGHT_JOIN id FROM B, A where B.ref = A.ref;
1 голос
/ 14 января 2009

Из ответов кажется, что вы делаете самое эффективное, что вы можете с SQL. Таблица A кажется большой проблемой, как насчет разделения ее на три отдельные таблицы, что-то вроде локальной версии шардинга? В качестве альтернативы, стоит ли денормализовать таблицу B в таблицу A, предполагая, что в столбце B слишком мало столбцов?

Наконец, вам может понадобиться купить более быструю коробку, чтобы запустить ее - ничто не заменит лошадиной силы!

Удачи.

0 голосов
/ 14 января 2009

ВЫБЕРИТЕ ИД ИЗ СОЕДИНЕНИЯ B НА A.ref = B.ref

Вы можете продолжить оптимизацию, используя подходящий тип соединения, например, LEFT JOIN

http://en.wikipedia.org/wiki/Join_(SQL)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...