2013-12-19 3 views
3

Я использую базу данных Oracle. У меня есть таблица, в которой одна из столбцов имеет XMLTYPE. Теперь проблема заключается в том, что мне нужно извлечь счетчик этих записей с XML с определенным корневым элементом и еще одним условием. Предположим, что XML сохраненную имеют следующие форматы:Как оптимизировать XQUERY в инструкции SELECT?

<ns1:Warehouse whNo="102" xmlns:ns1="xyz"> 
    <ns1:Building></ns1:Building> 
</ns1:Warehouse> 

и

<ns1:Warehouse whNo="102" xmlns:ns1="xyz"> 
    <ns1:Building>Owned</ns1:Building> 
</ns1:Warehouse> 

и есть другие XMLs с другими, чем склад корневых элементов

Теперь мне нужно принести те записи, которые имеют

  1. Корневой элемент как склад
  2. Строительный элемент, как пустой

Я написал следующий SQL-запрос:

select count(XMLQuery('declare namespace ns1="xyz.com"; 
         for $i in /*  
         where fn:local-name($i) eq "Warehouse" 
         and fn:string-length($i/ns1:Building) = 0 
         return <Test>{$i/ns1:Building}</Test>' 
         PASSING xml_response RETURNING CONTENT)) countOfWareHouses 
from test 

Здесь тест это имя таблицы и * xml_response * это имя столбца XmlType в таблице тест.

Этот запрос работает нормально, когда записи меньше. Я тестировал его около 500 записей в таблице, и время, которое требуется, составляет около 0,1 с. Но по мере увеличения количества записей в таблице время увеличивается. Когда я увеличил количество записей до 5000, время, затраченное на это, составило ~ 11 секунд. А для рабочей таблицы, где количество хранимых в настоящее время записей составляет 185000, этот запрос никогда не завершается.

Пожалуйста, помогите мне оптимизировать этот запрос или xquery.

Edit 1:

Я попытался с помощью этого:

select count(XMLQuery(
     'declare namespace ns1 = "xyz"; 
     for $i in/
     return /ns1:Warehouse[not(ns1:Building/text())]' 
     PASSING xml_response RETURNING CONTENT)) 
from test 

и

select count(XMLQuery(
     'declare namespace ns1 = "xyz"; 
     return /ns1:Warehouse[fn:string-length(ns1:Building)=0]' 
     PASSING xml_response RETURNING CONTENT)) 
from test 

Но это не работает.

Когда я пытаюсь запустить их, он запрашивает значения привязки для здания и склада.

+1

Ваш XQuery выглядит слишком сложным. Я уверен, можно считать пустые элементы в xquery. Этот [ответ] (http://stackoverflow.com/a/12448506/272735), похоже, касается вашей проблемы, за исключением того, что он подсчитывает непустые элементы. Надеюсь, поможет ! – user272735

ответ

1

Вместо того, где вы должны использовать предикаты, которые будут работать быстрее, как:

ns1:Warehouse[string-length(ns1:Building)=0] 
+0

Привет Навин, Спасибо за ваш ответ. Однако я попытался использовать это. Я не уверен, правильно ли я использую его. Я отредактировал исходный вопрос с правлением 1. Если вы можете проверить и предложить изменения, это было бы очень полезно. – plkmthr

1

Не используйте local-name(...), если нет необходимости. Тесты узлов, вероятно, будут быстрее и обеспечат использование индекса. Вы также можете удалить звонок string-length(...).

Поиск элементов <Warehouse/>, у которых нет текстовых узлов ниже их узла <Building/>. Если вы также хотите сканировать произвольные сундоды (включая атрибуты!), Используйте node() вместо text(). Если вы просто хотите убедиться, что есть где-то где-то еще как дочерний узел других узлов, используйте вместо этого ns1:Building//text(), например, в таких случаях: <ns1:Building><foo>bar</foo></ns1:Building>.

Это простое выражение XPath делает то, что вам нужно:

/ns1:Warehouse[not(ns1:Building/text())] 

Если вам нужно построить эти <Test/> элементы, используйте

for $warehouse in /ns1:Warehouse[not(ns1:Building/text())] 
return <Test>{$warehouse/ns1:Building}</Test> 

, которая должна быть реальной заменой к Вашему XQuery ,

Я только что понял, все, что вы хотите знать, это число, то лучше счетчик в XQuery (я не могу сказать вам, как читать один результат, то хотя):

count(/ns1:Warehouse[not(ns1:Building/text())]) 
+0

Привет, Дженс, Спасибо за ваш ответ. Однако я попытался использовать это. Я не уверен, правильно ли я использую его. Я отредактировал исходный вопрос с правлением 1. Если вы можете проверить и предложить изменения, это было бы очень полезно. – plkmthr

+1

Я только что понял, что вы строите свои собственные элементы результата. Обновлен мой ответ соответственно. Btw., Если вы получили сообщение об ошибке (error), всегда копируйте сообщение _exact_, включая номера ошибок, ... и не повторяйте его в своих собственных словах. –

+0

Йенс, создавая собственные элементы результата, не обязательно то, что я хочу, поскольку мне просто нужен счет. Элементы результата, если их можно избежать, станут долгожданным решением. – plkmthr