SQL-запрос с составным первичным ключом - PullRequest
2 голосов
/ 28 сентября 2011

Мне нужно получить информацию из двух баз данных. Один - ORACLE, а другой - DB2. В моей программе (C #) на первом этапе я получаю базовую информацию о моих объектах из базы данных ORACLE. На втором шаге я хочу добавить информацию, которая сохраняется в DB2. Таблица в DB2 имеет составной первичный ключ, и я не уверен, какой способ лучше всего запросить, или есть ли альтернатива, которую я не вижу в данный момент.

Например: COLUMN1 и COLUMN2 являются составным первичным ключом.

Вариант 1:

 SELECT * 
   FROM (SELECT COLUMN1, COLUNN2, COLUMN3, ..., COLUMN1||'_'||COLUMN2 AS ID 
           FROM TABLE1) AS TEMP 
  WHERE ID='2011_123456' 
     OR ID='2011_987654'

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

Вариант 2:

SELECT COLUMN1, COLUMN2, COLUMN3, ..., COLUMN1||'_'||COLUMN2 AS ID 
  FROM TABLE1 
 WHERE (COLUMN1='2011' AND COLUMN2='123456') 
    OR (COLUMN1='2011' AND COLUMN2='987654')

Это действительно быстро, но в любое время я получаю исключение SQL0954C (в куче приложения недостаточно места для обработки оператора).

Вариант 3:

SELECT COLUMN1, COLUMN2, COLUMN3, ..., COLUMN1||'_'||COLUMN2 AS ID 
  FROM TABLE1 
 WHERE COLUMN1 IN ('2011') 
   AND COLUMN2 IN ('123456','987654')

Этот также медленный по сравнению с вариантом 2.

Еще несколько цифр: ТАБЛИЦА 1 имеет в данный момент ок. 600 тыс. Строк

Я попробовал варианты и получил следующие времена выполнения:
Для 100 запрашиваемых объектов:
Вариант 1: 3900мс
Вариант 2: 218 мс

Для 400 запрашиваемых объектов:
Вариант 1: 10983мс
Вариант 2: 266мс

Для 500 запрашиваемых объектов:
Вариант 1: 12796мс
Вариант 2: исключение SQL0954C
Вариант 3: 7061мс

Только глядя на времена, я бы предпочел вариант 2, но есть проблема с исключением.

Базы данных не находятся под моим контролем, и у меня есть только права SELECT. Как вы думаете, что лучше для этого варианта использования? Есть ли другие возможности, которых я не вижу?

С уважением,
pkoeppe

Ответы [ 4 ]

0 голосов
/ 28 сентября 2011

Для варианта 3 измените

SELECT COLUMN1, COLUMN2, COLUMN3, ..., COLUMN1||'_'||COLUMN2 AS ID 
FROM TABLE1 
WHERE COLUMN1 IN ('2011') 
AND COLUMN2 IN ('123456','987654')

на:

SELECT COLUMN1, COLUMN2, COLUMN3, ..., COLUMN1||'_'||COLUMN2 AS ID 
FROM TABLE1 
WHERE COLUMN1 ='2011' 
AND COLUMN2 IN ('123456','987654')

Если вы ищете только одно значение для COLUMN1, нет причины использовать IN.

0 голосов
/ 28 сентября 2011

Оба варианта 2 и 3 являются нормальными.1 не является нормальным.
Поскольку вычисляемый идентификатор столбца в 1 отсутствует в каком-либо индексе, БД будет вынуждена выполнить хотя бы полное сканирование индекса.В 2 и 3 БД может использовать индексы как для столбца 1, так и для столбца 2, чтобы отфильтровать результат.

Чтобы выяснить, являются ли 2 или 3 лучшими, вам нужно изучить планы выполнения для этих запросов.

Еще одна заметка об индексах.Соответствующие индексы будут гораздо важнее, чем разница между 2 и 3. Даже если у вас есть только права выбора, вы можете предложить комбинированный индекс (column1, column2) для администратора баз данных, если таких индексов уже нет.

Редактировать
Другой распространенный подход, когда у вас много значений в WHERE COL IN (...), - это создать временную таблицу (если у вас есть разрешение) со всеми значениями и вместо этого соединиться с этой временной таблицей.Иногда вам также нужно создать индекс для временной таблицы, чтобы она работала хорошо.
В некоторых СУБД: вы можете использовать табличные параметры вместо временных таблиц, но я не могу найти ничего подобного для DB2.

0 голосов
/ 28 сентября 2011

SQL0954C может быть решен путем настройки конфигурации вашей системы.Вы уже исследовали этот проспект? Узнать больше .

0 голосов
/ 28 сентября 2011

Не могли бы вы сделать модификацию варианта 2, которая

  • определил курсор
  • массово собрал 100 строк (например) в таблицу pl / sql
  • сделай свою обработку
  • получить следующие 100 строк

Например, см. http://oracletoday.blogspot.com/2005/11/bulk-collect_15.html

У меня была проблема, очень похожая на эту проблему с Oracle и Informix.

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