Как оптимизировать SQL-запрос с помощью многих тысяч предложений WHERE - PullRequest
2 голосов
/ 19 апреля 2010

У меня есть ряд запросов к очень большой базе данных, и у меня есть сотни тысяч OR в предложениях WHERE. Какой самый лучший и простой способ оптимизировать такие запросы SQL? Я нашел несколько статей о создании временных таблиц и использовании объединений, но я не уверен. Я новичок в серьезном SQL и сокращаю и вставляю результаты из одного в другое.

SELECT doc_id, language, author, title FROM doc_text WHERE language='fr' OR language='es'
SELECT doc_id, ref_id FROM doc_ref WHERE doc_id=1234567 OR doc_id=1234570 OR doc_id=1234572 OR doc_id=1234596 OR OR OR ...
SELECT ref_id, location_id FROM ref_master WHERE ref_id=098765 OR ref_id=987654 OR ref_id=876543 OR OR OR ...
SELECT location_id, location_display_name FROM location
SELECT doc_id, index_code, FROM doc_index WHERE doc_id=1234567 OR doc_id=1234570 OR doc_id=1234572 OR doc_id=1234596 OR OR OR x100,000

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

Ответы [ 4 ]

7 голосов
/ 19 апреля 2010

Кажется, я только что ответил на свой вопрос ... ВСТАВЛЕННЫЕ СТОЛЫ!

SELECT doc_text.doc_id, doc_text.language, doc_text.author, doc_text.title, doc_ref.ref_id, ref_master.location_id, location.location_display_name, doc_index.doc_id, doc_index.display_heading
FROM DOC_TEXT, DOC_REF, REF_MASTER, LOCATION, DOC_INDEX
WHERE
    doc_text.language='fr' OR doc_text.language='es'
AND
    doc_text.doc_id=doc_ref.doc_id
AND
    doc_ref.doc_id=ref_master.ref_id
AND
    ref_master.location_id=location.location_id
AND
    doc_text.doc_id=doc_index.doc_id
5 голосов
/ 19 апреля 2010

Самый простой способ сделать это - это:

  • Создайте индексы для столбцов, по которым выполняется фильтрация (language, ref_id, doc_id и т. Д.), По крайней мере, дважды проверьте их наличие. Сделайте их кластеризованными, если они являются основным индексом таблицы.
  • Создание вспомогательных таблиц, содержащих условия (добавление / удаление условий с помощью операторов INSERT / DELETE), их индексирование.
  • вместо 1000 компонентов "ИЛИ" создайте ВНУТРЕННЕЕ СОЕДИНЕНИЕ:

Итак ...

SELECT doc_id, language, author, title 
  FROM doc_text
 WHERE language='fr' OR language='es'

становится

INSERT language_search (language) VALUES ('fr')
INSERT language_search (language) VALUES ('es')
/* and 50 more */

SELECT dt.doc_id, dt.language, dt.author, dt.title 
  FROM doc_text dt
       INNER JOIN language_search ls ON dt.language = ls.language
3 голосов
/ 19 апреля 2010

Вместо множества условий в одном поле вы можете использовать ключевое слово in:

SELECT doc_id, ref_id FROM doc_ref WHERE doc_id in (1234567, 1234570, 1234572, 1234596, ...)

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

Редактировать

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

select
  doc_text.doc_id, doc_text.language, doc_text.author, doc_text.title,
  doc_ref.ref_id, ref_master.location_id, location.location_display_name,
  doc_index.doc_id, doc_index.display_heading
from DOC_TEXT
inner join DOC_REF on doc_text.doc_id = doc_ref.doc_id
inner join REF_MASTER on doc_ref.doc_id = ref_master.ref_id
inner join LOCATION on ref_master.location_id = location.location_id
inner join DOC_INDEX on doc_text.doc_id = doc_index.doc_id
where
  doc_text.language in ('fr', 'es')
0 голосов
/ 19 апреля 2010

Я думаю, что ваша настоящая проблема в том, что вы не участвуете в таблицах.

это предположение, но я держу пари, что вы выполняете запрос, затем получаете все идентификаторы в своем приложении и затем запускаете другой запрос, ГДЕ все строки соответствуют предыдущему запросу. Вы бы значительно повысили производительность, написав запрос с объединением:

SELECT
    *
    FROM YourTableA            a
        INNER JOIN YourTableB  b ON a.ID=b.ID
    WHERE a. .....

затем обработайте один набор результатов в вашем приложении.

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