![]() |
#1 |
MCTS
|
![]()
Всем превед!
Представим следующую ситуацию: есть табличка LedgerTrans с большим количеством записей (порядка 500 тыс.). Соответственно нужно выбрать из нее только записи, у которых счет равен 10.100 и 10.200. Внимание - вопрос! Какой запрос отработает быстрее? 1. select LedgerTrans exist join param where LedgerTrans.AccountNum == param.AccountNum (param - табличка, в которой перечислены нужные счета, в нашем случае 10.100 и 10.200). 2. select LedgerTrans where LedgerTrans.AccountNum like "10.*" Последний раз редактировалось CDR; 11.01.2008 в 12:38. |
|
![]() |
#2 |
Участник
|
А если взять да попробовать?
![]() |
|
![]() |
#3 |
Участник
|
А так
X++: select LedgerTrans where LedgerTrans.AccountNum >= "10." && LedgerTrans.AccountNum <= "10.Я" // или LedgerTrans.AccountNum < "10<соедующий символ после точки>" |
|
![]() |
#4 |
MCTS
|
|
|
![]() |
#5 |
Участник
|
Если по AccountNum есть индекс, то с точки зрения SQL - like будет меньше ресурсов потреблять чем join. И потом exist join не факт что будет 1 запросом работать на сервере.
|
|
![]() |
#6 |
Участник
|
Доп вопросы:
1. Какое число записей в LedgerTrans соответствуют условию ? 2. Какие индексы есть на таблице LedgerTrans ? 3. Таблица Param постоянная или временная ? 4. Какие индексы есть на таблице Param ? 5. Какое выравнивание у поля LedgerTrans.AccountNum, влево или вправо ? |
|
![]() |
#7 |
MCTS
|
Цитата:
![]() |
|
![]() |
#8 |
Участник
|
|
|
![]() |
#9 |
Участник
|
Цитата:
Сообщение от CDR
![]() Всем превед!
Представим следующую ситуацию: есть табличка LedgerTrans с большим количеством записей (порядка 500 тыс.). Соответственно нужно выбрать из нее только записи, у которых счет равен 10.100 и 10.200. Внимание - вопрос! Какой запрос отработает быстрее? 1. select LedgerTrans exist join param where LedgerTrans.AccountNum == param.AccountNum (param - табличка, в которой перечислены нужные счета, в нашем случае 10.100 и 10.200). 2. select LedgerTrans where LedgerTrans.AccountNum like "10.*" |
|
![]() |
#10 |
MCTS
|
|
|
![]() |
#11 |
Участник
|
tourist, я полагаю теоретически вариант 2. быстрее, так как SQL в 1. варианте не знает, что можно обойтись index scan по AccountNum, и в 1 варианте сначала сделать tableScan по param, потом nestedLoop по всем записям и indexSсan по LedgerTranns
|
|
![]() |
#12 |
MCTS
|
Хм... Только что опробовал обе конструкции на тестовой табличке с количеством записей около 200 тыс. Результат поразил, однако...
Конструкция с exist join выигрывает в скорости более чем в 10 раз ![]() Ваши каменты по этому поводу? ![]() |
|
![]() |
#13 |
Участник
|
А планчики можно?
А мой вариант? |
|
![]() |
#14 |
Участник
|
Честно говоря, тоже думал, что второй будет работать быстрее.
Особенно учитывая, что у LedgerTrans есть индекс, где первым полем идет AccountNum. Планы бы действительно интересно было посмотреть. |
|
![]() |
#15 |
Модератор
|
Цитата:
Например, запрос в QA без фильтра на DataAreaId ну и опять же метания между Цитата:
в нашем случае 10.100 и 10.200)
Цитата:
where LedgerTrans.AccountNum like "10.*"
покажи (ничего, что я на ТЫ? ![]()
__________________
-ТСЯ или -ТЬСЯ ? |
|
![]() |
#16 |
Участник
|
Думаю, что Join быстрее при наличии индекса, так как с Like он не используется
|
|
![]() |
#17 |
Участник
|
select LedgerTrans where LedgerTrans.AccountNum >= "10."
&& LedgerTrans.AccountNum < "10/" |
|
![]() |
#18 |
Участник
|
![]() |
|
![]() |
#19 |
MCTS
|
![]()
Условия и план проведенного мной теста:
1. Создаем тестовую табличку Trans из двух полей: Id и Name. 2. На табличке создаем неуникальный индекс по полю Id, который делаем кластерным. 3. Создаем джобик, который в цикле наполняет эту таблицу значениями. У меня был такой: внешний цикл i от 1 до 40 000, внутренний цикл j от 1 до 12. Во внутреннем цикле вставляются записи в табличку из пункта 1 (Id = strfmt('%1',j)). Джобик рекомендуется запускать на довольно мощном серваке, а то уснуть можно ![]() 4. Создаем табличку Params с одним полем Id, На табличке создаем уникальный индекс, который делаем Primary и кластерным. В табличку вводим значения "1", "10", "11", "12". 5. Пишем тестовый джоб. В моем случае было два select'а: select count(recId) from Trans exists join Params where Trans.Id == Params.Id; select count(recId) from Trans where Trans.Id like '1*'; Между select'ами смотрим время (я пользовался WinAPI::getTickCount() вместо timeNow(), дает более точное значение ). 6. Джобик запускаем пару раз, что б снизить влияние всякого там кэша. Затем можно поменять select'ы местами, для большей уверености ![]() 7. Результатами делимсо тут. ![]() У меня, как я уже писал, exists join "сделал" like более чем в 10 раз ![]() |
|
![]() |
#20 |
MCTS
|
|
|
|
Опции темы | Поиск в этой теме |
Опции просмотра | |
|