|
LIMIT, JOIN и использование индексов
|
|||
---|---|---|---|
#18+
Задавал такой вопрос в форуме PostgreSQL. Там ответили что такой возможности там нет, но учитывая что там и predicate push down нет, а система кроссплатформенна возник принципиальный вопрос есть ли такая возможность в других СУБД. Ссылка на тот форум] http://www.sql.ru/forum/actualthread.aspx?tid=924906 Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29.
Такие запросы нужны для динамических списков с сортировкой по связанному полю. План выполнения : Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11.
То есть join'им таблицы, сортируем, находим верхние 50 и фиг с ними с индексами. В итоге считывается вся база. Соответственно есть СУБД, которые догадываются бежать по B_x, для каждой записи бежать по A_b, выкидывая в результат соответствующие записи пока не наберется 50 записей? То есть фиг с ним бы с predicate push down, его можно обойти самому проталкивая контекст внутрь (что даже эффективнее иногда использования эвристик СУБД), а вот перестроить запрос с LIMIT'ом не понятно как :( Точнее можно но это будет такая трехэтажная конструкция, что проще действительно materialize'ить. ... |
|||
:
Нравится:
Не нравится:
|
|||
10.03.2012, 09:38 |
|
LIMIT, JOIN и использование индексов
|
|||
---|---|---|---|
#18+
Bond_JamesBond, во первых объем данных слишком мал, любой нормальный оптимизатор примет решение вычитать фулсканом таблицы, т.к. это на таком объеме дешевле (пара многоблочных чтений). если увеличить размер то оракл, например, думаю и сам нестед луп применит. даже если не применит его оптимизатор всегда можно запинать хинтами и заставить применить нестед луп. ... |
|||
:
Нравится:
Не нравится:
|
|||
10.03.2012, 13:55 |
|
LIMIT, JOIN и использование индексов
|
|||
---|---|---|---|
#18+
Во-первых какая у тебя версия PG и спроси в постгресовой ветке она уже поддерживает IOS? Во-вторых о чем уже сказал йошка - слишком малый объем данных чтобы делать NLJ. В-третьих если все таки поддержка IOS у тебя есть и хочешь использовать индексы для JOIN, то создай индекс Код: plsql 1. 2. 3. 4.
В-четвёртых расскажи, где у тебя в запросе предикаты, которые надо "predicate push down". И в-пятых расшифруй "Соответственно есть СУБД, которые догадываются бежать по B_x, для каждой записи бежать по A_b, выкидывая в результат соответствующие записи пока не наберется 50 записей?" ... |
|||
:
Нравится:
Не нравится:
|
|||
10.03.2012, 16:21 |
|
LIMIT, JOIN и использование индексов
|
|||
---|---|---|---|
#18+
CREATE INDEX, Специально увеличил объем до 1 миллиона записей в А и 10к в В, принципиально ничего не поменялось : "Limit (cost=72845.26..72845.38 rows=50 width=16) (actual time=752.861..752.866 rows=50 loops=1)" " -> Sort (cost=72845.26..75341.27 rows=998403 width=16) (actual time=752.858..752.861 rows=50 loops=1)" " Sort Key: b.x, a.key0" " Sort Method: top-N heapsort Memory: 20kB" " -> Hash Join (cost=270.00..39679.03 rows=998403 width=16) (actual time=2.730..566.940 rows=1000000 loops=1)" " Hash Cond: (a.b = b.key0)" " -> Seq Scan on a (cost=0.00..14425.00 rows=1000000 width=8) (actual time=0.035..128.657 rows=1000000 loops=1)" " -> Hash (cost=145.00..145.00 rows=10000 width=8) (actual time=2.684..2.684 rows=10000 loops=1)" " Buckets: 1024 Batches: 1 Memory Usage: 313kB" " -> Seq Scan on b (cost=0.00..145.00 rows=10000 width=8) (actual time=0.006..1.064 rows=10000 loops=1)" "Total runtime: 752.969 ms" Версия СУБД: "PostgreSQL 9.1rc1, compiled by Visual C++ build 1500, 32-bit" Также на 9.0 проверено, очень сомневаюсь что в минор релизе добавили index only scan, да и не совсем понимаю причем он тут. Также не совсем понимаю чем ей поможет индекс по key0, x когда она знает что key0 primary key и для него ровно один x. Predicate push down привел для примера фичи, которую не поддерживает postgre, но поддерживают другие СУБД. Возможно здесь аналогичный случай. Если бы я писал вручную этот запрос то я бы грубо говоря сделал так : (привожу в синтаксисе "файл-серверной" СУБД например Foxpro, надеюсь будет понятно) SET INDEX TO B_x IN B SET INDEX TO A_b IN A SELECT B i=0 SCAN ALL SELECT A SET KEY TO B.key0 SCAN ALL i=i+1 MESSAGEBOX(A.key0) // вывод результата IF i>50 // RETURN ENDIF ENDSCAN SELECT B ENDSCAN Соответственно такой подход сделал бы все максимум за 50 итераций а не за 1 миллион как в моем случае ... |
|||
:
Нравится:
Не нравится:
|
|||
10.03.2012, 23:11 |
|
LIMIT, JOIN и использование индексов
|
|||
---|---|---|---|
#18+
С табуляциями : Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11.
Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16.
... |
|||
:
Нравится:
Не нравится:
|
|||
10.03.2012, 23:13 |
|
LIMIT, JOIN и использование индексов
|
|||
---|---|---|---|
#18+
Второй индекс для SMJ. У тебя соединение по одним столбцам, один из которых не уникальный, сортировка по другим, первый из которых не уникальный. А так какой план будет? (обе таблицы увеличил в 100 раз, добавил индекс, и правое соединение) Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34.
... |
|||
:
Нравится:
Не нравится:
|
|||
10.03.2012, 23:24 |
|
LIMIT, JOIN и использование индексов
|
|||
---|---|---|---|
#18+
CREATE INDEX, Да в общем то такой же Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11.
... |
|||
:
Нравится:
Не нравится:
|
|||
11.03.2012, 00:26 |
|
LIMIT, JOIN и использование индексов
|
|||
---|---|---|---|
#18+
Bond_JamesBond, Жесть. Установил Oracle 11g, он даже случай SELECT * FROM (SELECT * FROM A JOIN B ON B.key0=A.b ORDER BY B.x, B.key0) t0 WHERE rownum < 50; не разбирает. Хотя может я что-то не так делаю, буду еще разбираться... ... |
|||
:
Нравится:
Не нравится:
|
|||
11.03.2012, 11:32 |
|
LIMIT, JOIN и использование индексов
|
|||
---|---|---|---|
#18+
Bond_JamesBondBond_JamesBond, Жесть. Установил Oracle 11g, он даже случай SELECT * FROM (SELECT * FROM A JOIN B ON B.key0=A.b ORDER BY B.x, B.key0) t0 WHERE rownum < 50; не разбирает. Хотя может я что-то не так делаю, буду еще разбираться... все верно, фулсканить гораздо эффективней: Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71. 72. 73. 74. 75. 76. 77. 78. 79. 80. 81. 82. 83. 84. 85. 86. 87. 88. 89. 90. 91. 92. 93. 94. 95. 96. 97. 98. 99. 100. 101. 102. 103. 104. 105. 106. 107.
т.е. фулсканы дают в 1.5 раза меньше физических чтений и на порядок меньше логических. ... |
|||
:
Нравится:
Не нравится:
|
|||
11.03.2012, 14:13 |
|
LIMIT, JOIN и использование индексов
|
|||
---|---|---|---|
#18+
Bond_JamesBond, пральна. Попробуй rownum<5 / LIMIT 5 или ещё раз в 10-100 увеличь таблицы. Yo. А че ты покрывающий индекс по соединяемым полям не сделал для SMJ? ... |
|||
:
Нравится:
Не нравится:
|
|||
11.03.2012, 14:38 |
|
LIMIT, JOIN и использование индексов
|
|||
---|---|---|---|
#18+
Yo.!, Так а где использование B_x? То есть получается что она бежит по B полностью JOIN'ит NESTED'а с A, и потом идет все та же сортировка и отрезание. С использование B_x и A_b по определению не будет больше 50 чтений. А никакие не тысячи. Попробовал rownum <= 1 те же яйца. ... |
|||
:
Нравится:
Не нравится:
|
|||
11.03.2012, 19:03 |
|
LIMIT, JOIN и использование индексов
|
|||
---|---|---|---|
#18+
впрягусь и попробую объяснить, как я понял вопрос Bond_JamesBond. SELECT * FROM A JOIN B ON B.key0=A.b ORDER BY B.x, A.key0 LIMIT 50; может ли какая-нибудь СУБД выполнять этот запрос таким образом: 1) по индексу B(x) выбрать все записи с минимальным значением x, 2) присоединить к ним nestedloop-ом записи из A по условию B.key0=A.b, 3) отсортировать полученный набор записей по A.key0, 4) выдать записи наружу, и проверить кол-во на лимит 50 5) если меньше лимита, вернуться к пункту 1 с условием выбирать записи с минимальным x строго больше значения x на предыдущем шаге ... |
|||
:
Нравится:
Не нравится:
|
|||
13.03.2012, 12:31 |
|
LIMIT, JOIN и использование индексов
|
|||
---|---|---|---|
#18+
LeXa NalBat, ему уже все показали и разжували в оракловой ветке http://www.sql.ru/forum/actualthread.aspx?tid=925205 ... |
|||
:
Нравится:
Не нравится:
|
|||
13.03.2012, 12:48 |
|
LIMIT, JOIN и использование индексов
|
|||
---|---|---|---|
#18+
LeXa NalBatвпрягусь и попробую объяснить, как я понял вопрос Bond_JamesBond. SELECT * FROM A JOIN B ON B.key0=A.b ORDER BY B.x, A.key0 LIMIT 50; может ли какая-нибудь СУБД выполнять этот запрос таким образом: 1) по индексу B(x) выбрать все 50 записи с минимальным значением x, 2) присоединить к ним nestedloop-ом записи из A по условию B.key0=A.b, 3) отсортировать полученный набор записей по B.x, A.key0 , 4) выдать записи наружу, и проверить кол-во на лимит 50 5) если меньше лимита, вернуться к пункту 1 с условием выбирать записи с минимальным x строго больше значения x на предыдущем шаге ... |
|||
:
Нравится:
Не нравится:
|
|||
13.03.2012, 15:00 |
|
LIMIT, JOIN и использование индексов
|
|||
---|---|---|---|
#18+
все 50 нет, именно все строки с минимальным значением x, потому что присоединяющиеся строки с минимальными значениями A.key0 могут прийтись не на Ваши случайные 50 строк из B. (также соответствующих(-ей) строк(-и) для присоединения может не найтись в A.) B.x, A.key0 нет, достаточно отсортировать группу по A.key0, потому что все строки в группе имеют одинаковое значение B.x, и поэтому сортировка по A.key0 эквивалентна сортировке по B.x, A.key0. PS: неужели я тоже непонятно объяснил задачу? :) ... |
|||
:
Нравится:
Не нравится:
|
|||
13.03.2012, 17:16 |
|
LIMIT, JOIN и использование индексов
|
|||
---|---|---|---|
#18+
LeXa NalBatвсе 50 нет, именно все строки с минимальным значением x, потому что присоединяющиеся строки с минимальными значениями A.key0 могут прийтись не на Ваши случайные 50 строк из B. (также соответствующих(-ей) строк(-и) для присоединения может не найтись в A.) B.x, A.key0 нет, достаточно отсортировать группу по A.key0, потому что все строки в группе имеют одинаковое значение B.x, и поэтому сортировка по A.key0 эквивалентна сортировке по B.x, A.key0. PS: неужели я тоже непонятно объяснил задачу? :) А если все B.x уникальны, то как оптимальней? ... |
|||
:
Нравится:
Не нравится:
|
|||
14.03.2012, 03:21 |
|
LIMIT, JOIN и использование индексов
|
|||
---|---|---|---|
#18+
50А если все B.x уникальны, то как оптимальней?я не ставлю вопрос о выборе плана ("как оптимальней?") среди разных вариантов, ответ на который ищет планировщик (в постгресе planner). я спрашиваю, может ли какая-нибудь СУБД исполнить (в постгресе executor) такой план запроса. (предположим, что планировщик выбрал именно его.) (описанный мною план подошел бы и для уникальных B.x. особенность только в том, что каждый раз на первом шаге будет выбираться ровно одна строка с минимальным x. поэтому при наличии индекса A(b,key0) на втором шаге можно присоединять строки из A по этому индексу, и набор строк уже будет в нужном порядке, сортировка натретьем шаге в этом случае не нужна.) PS: придумал более простой пример, как мне кажется, на ту же тему. предположим в таблице A есть индекс по полю (f1). запрос: SELECT * FROM A ORDER BY f1, f2 LIMIT 50 может ли какая-нибудь СУБД выполнить этот запрос с использованием индекса по (f1), не пересортировывая все строки A? например по алгоритму: 1) по индексу A(f1) выбрать все записи с минимальным значением f1, 2) 3) отсортировать полученный набор записей по A.f2, 4) выдать записи наружу, и проверить кол-во на лимит 50 5) если меньше лимита, вернуться к пункту 1 с условием выбирать записи с минимальным f1 строго больше значения f1 на предыдущем шаге ... |
|||
:
Нравится:
Не нравится:
|
|||
14.03.2012, 10:04 |
|
LIMIT, JOIN и использование индексов
|
|||
---|---|---|---|
#18+
50А если все B.x уникальны, то как оптимальней? В этом случае наличие A.Key0 в order by теряет смысл вместе с вопросом ТСа. Posted via ActualForum NNTP Server 1.5 ... |
|||
:
Нравится:
Не нравится:
|
|||
14.03.2012, 13:02 |
|
LIMIT, JOIN и использование индексов
|
|||
---|---|---|---|
#18+
Dimitry Sibiryakov50А если все B.x уникальны, то как оптимальней?В этом случае наличие A.Key0 в order by теряет смысл вместе с вопросом ТСа.нет. потому что A.b не уникальны. и к одной строке из B с уникальным B.x может присоединиться несколько строк из A, эту группу нужно отсортировать по A.key0. ... |
|||
:
Нравится:
Не нравится:
|
|||
14.03.2012, 14:59 |
|
LIMIT, JOIN и использование индексов
|
|||
---|---|---|---|
#18+
Bond_JamesBond... То есть join'им таблицы, сортируем, находим верхние 50 и фиг с ними с индексами. В итоге считывается вся база. Соответственно есть СУБД, которые догадываются бежать по B_x, для каждой записи бежать по A_b, выкидывая в результат соответствующие записи пока не наберется 50 записей? ... Код для СУБД CachéClass test.A Extends %Persistent { Index Ab On b; Property b As %Integer; ClassMethod Fill(isSmall As %Boolean = {$$$YES}) { ; удаляем данные do ##class(test.A).%KillExtent() do ##class(test.B).%KillExtent() ; заполняем данными if isSmall { for i=1:1:10000 &sql(insert into test.A set b=:i#100+1) for i=1:1:100 &sql(insert into test.B set x=:i*37#100) }else{ set N=1000000 for i=1:1:N set ^test.AD(i)=$lb("",i#100+1) set ^test.AD=N set N=10000 for i=1:1:N set ^test.BD(i)=$lb("",i*37#100) set ^test.BD=N ; строим индексы do ##class(test.A).%BuildIndices(,1,1) do ##class(test.B).%BuildIndices(,1,1) } ; настраиваем таблицы do $system.SQL.TuneTable("test.A",1,1) do $system.SQL.TuneTable("test.B",1,1) } } Class test.B Extends %Persistent { Index Bx On x; Property x As %Integer; } 10000/100 записей соответственно 1) Запрос по умолчанию select TOP 50 * from test.A JOIN test.B ON B.ID=A.b ORDER BY B.x, A.ID Быстродействие: 0.003 Секунд 615 глобальных ссылок Код: xml 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18.
2) Запрос с отключённым индексом Bx select TOP 50 * from %IGNOREINDEX test.B.Bx test.A JOIN test.B ON B.ID=A.b ORDER BY B.x, A.ID Быстродействие: 0.006 Секунд 1919 глобальных ссылок Код: xml 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18.
3) Все индексы отключены select TOP 50 * from %IGNOREINDEX test.A.Ab,test.B.Bx test.A JOIN test.B ON B.ID=A.b ORDER BY B.x, A.ID Быстродействие: 0.035 Секунд 40840 глобальных ссылок Код: xml 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17.
1000000/10000 записей соответственно 1) Запрос по умолчанию select TOP 50 * from test.A JOIN test.B ON B.ID=A.b ORDER BY B.x, A.ID Быстродействие: 0.015 Секунд 10713 глобальных ссылок Код: xml 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18.
2) Запрос с отключённым индексом Bx select TOP 50 * from %IGNOREINDEX test.B.Bx test.A JOIN test.B ON B.ID=A.b ORDER BY B.x, A.ID Быстродействие: 0.101 Секунд 91118 глобальных ссылок Код: xml 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18.
3) Все индексы отключены select TOP 50 * from %IGNOREINDEX test.A.Ab,test.B.Bx test.A JOIN test.B ON B.ID=A.b ORDER BY B.x, A.ID Быстродействие: 2.941 Секунд 4000840 глобальных ссылок Код: xml 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17.
10000000/100000 записей соответственно 1) Запрос по умолчанию select TOP 50 * from test.A JOIN test.B ON B.ID=A.b ORDER BY B.x, A.ID Быстродействие: 0.124 Секунд 102513 глобальных ссылок Код: xml 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18.
Caché for Windows (x86-64) 2012.2 (Build 528_1U) ... |
|||
:
Нравится:
Не нравится:
|
|||
14.03.2012, 20:30 |
|
LIMIT, JOIN и использование индексов
|
|||
---|---|---|---|
#18+
LeXa NalBatпредположим в таблице A есть индекс по полю (f1). запрос: SELECT * FROM A ORDER BY f1, f2 LIMIT 50 может ли какая-нибудь СУБД выполнить этот запрос с использованием индекса по (f1), не пересортировывая все строки A?Если даже план оптимизатором выбран неэффективный, ему всегда можно подсказать. Например: Код для СУБД CachéClass test.C Extends %Persistent { Index idxF1 On f1; Property f1 As %Integer; Property f2 As %Integer; ClassMethod Fill() { do DISABLE^%NOJRN do ..%KillExtent() ; для ускорения заполнения таблицы случайными значениями для 100млн. записей использовался прямой доступ set N=100000000 for i=1:1:N { set f1=$random(50000)+i set f2=$random(i)+50000 set ^test.CD(i)=$lb("",f1,f2) //запись данных set ^test.CI("idxF1",f1,i)="" //запись индекса } set ^test.CD=N do ENABLE^%NOJRN do $system.SQL.TuneTable("test.C",1,1) } } Результат для 100млн. записей: Быстродействие: 0.005 Секунд 960 глобальных ссылок Код: xml 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22.
... |
|||
:
Нравится:
Не нравится:
|
|||
15.03.2012, 10:48 |
|
LIMIT, JOIN и использование индексов
|
|||
---|---|---|---|
#18+
servitLeXa NalBatпредположим в таблице A есть индекс по полю (f1). запрос: SELECT * FROM A ORDER BY f1, f2 LIMIT 50 может ли какая-нибудь СУБД выполнить этот запрос с использованием индекса по (f1), не пересортировывая все строки A?select TOP 50 * from test.C where f1 in (select TOP 50 f1 from test.C order by f1) order by f1,f2нет. такой запрос не эквивалентен исходному. например в таблице A есть 100 строк с одинаковым минимальным значением f1. исходный запрос должен выдать те 50 из этой сотни, у которых меньше значения f2. а Ваш запрос сначала выберет случайные 50 строк из этой сотни, то есть может выбрать и с бОльшими значениями f1, в этом и ошибка, а потом их упорядочит. PS: как обсудили в этой и других темах (в постгресовом и оракловом разделах), можно так переформулировать запрос (CTE, unnest), чтобы он стал выполняться быстро по желаемому плану или приблизительно так. но интересует именно возможность выбора и исполнения сервером БД такого быстрого плана именно для такого простого запроса, без переформулировок. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.03.2012, 11:16 |
|
LIMIT, JOIN и использование индексов
|
|||
---|---|---|---|
#18+
servit, Cache зачет тогда... и луч позора Oracle и MSSQL. Смущает только без индексов для 1млн выполнение 2,5 секунды, остальные субд справляются за 300-500мс. Может к Cache адаптер сделать :)... Как у них кстати с SQL compliance, в смысле поддержка WINDOW функций, RECURSIVE CTE, и наличие каких-нибудь дебильных ограничений, типа того что временную таблицу нельзя юзать 2 раза в одном запросе (помню убило меня такое ограничение в MySQL). ... |
|||
:
Нравится:
Не нравится:
|
|||
15.03.2012, 11:25 |
|
LIMIT, JOIN и использование индексов
|
|||
---|---|---|---|
#18+
LeXa NalBat...а Ваш запрос сначала выберет случайные 50 строк из этой сотни...Запрос сперва выберет первые 50 минимальных уникальных значений поля f1 , затем на их основе выберет все строки из таблицы с этими значениями и уже отсортирует полученные строки по полям f1 и f2, ограничив затем результат до 50. Приведите пример данных, так как на моих данных (я пробовал несколько комбинаций) результаты в обоих случаях совпадают. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.03.2012, 12:04 |
|
LIMIT, JOIN и использование индексов
|
|||
---|---|---|---|
#18+
Bond_JamesBond, Если вы пользуете Коше, то пользуйте его COS(вроде-бы)... Просто то-же самое, но написанное на SQL будет в 1,5 - 2 раза медленней. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.03.2012, 12:27 |
|
LIMIT, JOIN и использование индексов
|
|||
---|---|---|---|
#18+
servitLeXa NalBat...а Ваш запрос сначала выберет случайные 50 строк из этой сотни...Запрос сперва выберет первые 50 минимальных уникальных значений поля f1 ... Приведите пример данных, так как на моих данных (я пробовал несколько комбинаций) результаты в обоих случаях совпадают.разве Cache в запросе "select TOP 50 f1 from test.C order by f1" уникализирует выдачу DISTINCT-ом? мой контр-пример - "например в таблице A есть 100 строк с одинаковым минимальным значением f1". ... |
|||
:
Нравится:
Не нравится:
|
|||
15.03.2012, 13:14 |
|
LIMIT, JOIN и использование индексов
|
|||
---|---|---|---|
#18+
LeXa NalBatразве Cache в запросе "select TOP 50 f1 from test.C order by f1" уникализирует выдачу DISTINCT-ом?Если вызвать этот запрос отдельно, то нет - вернутся 50 одинаковых значений. Но в контексте подзапроса для конструкции TOP/ORDER BY действуют специальные оптимизации . Даже запрос select TOP 50 * from test.C where f1 in (select top all f1 from test.C order by f1) order by f1,f2 отрабатывает быстро. LeXa NalBatмой контр-пример - "например в таблице A есть 100 строк с одинаковым минимальным значением f1".Пробую: &sql(truncate table test.C) for i=1:1:60 &sql(insert into test.C(f1,f2) values(2,10)) for i=1:1:40 &sql(insert into test.C(f1,f2) values(2,1)) for i=1:1:60 &sql(insert into test.C(f1,f2) values(1,10)) for i=1:1:40 &sql(insert into test.C(f1,f2) values(1,1)) Все три варианта запроса возвращают одинаковый результат: #IDf1f2116111216211316311416411516511616611716711816811916911101701111171111217211131731114174111517511161761117177111817811191791120180112118111221821123183112418411251851126186112718711281881129189113019011311911132192113319311341941135195113619611371971138198113919911402001141101110421021104310311044104110451051104610611047107110481081104910911050110110 ... |
|||
:
Нравится:
Не нравится:
|
|||
15.03.2012, 15:23 |
|
LIMIT, JOIN и использование индексов
|
|||
---|---|---|---|
#18+
Bond_JamesBond...Смущает только без индексов для 1млн выполнение 2,5 секунды, остальные субд справляются за 300-500мс....Ничего определённого не могу сказать на этот счёт: кэширование, умение оптимизатора создавать/использовать неявные индексы, др. Можно попробовать оптимизатору через хинты явно указать не использовать никаких индексов. Bond_JamesBondМожет к Cache адаптер сделать :)... Попробуйте . Помимо поддержки Java, .NET, Delphi, PHP и др. разработчики недавно добавили нативную поддержку для node.js . Кроме реляционного интерфейса Вы ещё можете попробовать объектный или прямой. Bond_JamesBondКак у них кстати с SQL compliance, в смысле поддержка WINDOW функций, RECURSIVE CTE, и наличие каких-нибудь дебильных ограничений, типа того что временную таблицу нельзя юзать 2 раза в одном запросе (помню убило меня такое ограничение в MySQL)Свои ограничения есть, как и везде. Например, нельзя cделать в федеративном хранилище гетерогенные запросы к таблицам от разных источников данных. То есть, если у Вас одна таблица принадлежит Oracle, а другая допустим MySQL, то над ними вместе нельзя сделать, к примеру, операцию JOIN. SQL-92 Compliance Caché SQL Reference WarstoneЕсли вы пользуете Коше, то пользуйте его COS(вроде-бы)... Просто то-же самое, но написанное на SQL будет в 1,5 - 2 раза медленней.Примеры выше показывают, что и на SQL скорость бывает приемлемая. Хотя, конечно, если есть необходимость добиться ещё большей скорости, то всегда можно "спуститься" с SQL и/или объектов на уровень ниже (NoSQL). Если не получается декларативно сделать быстро, то можно сделать это императивно. COS (Caché ObjectScript) - более универсальный язык (потомок M ) и позволяет писать любой код с использованием объектов/классов, запросов; c доступом к низкоуровневым структурам (глобалам). На нём можно писать также код, не относящийся напрямую к работе с данными, например: работа с почтой, файлами, X.509 сертификатами, XML, SOAP и т.д. В СУБД Caché для этого есть довольно богатая библиотека готовых классов . ... |
|||
:
Нравится:
Не нравится:
|
|||
15.03.2012, 15:50 |
|
LIMIT, JOIN и использование индексов
|
|||
---|---|---|---|
#18+
servit, Не, нас интересует только "базовый" SQL. И вообщем, то поддержка SQL 2003 - (в 99- поддержка RECURSIVE CTE, в 2003 - window функции), все остальное - не критично. Вот что-то их я не нашел (хотя может невнимательно искал). Может поделитесь ссылкой? ... |
|||
:
Нравится:
Не нравится:
|
|||
15.03.2012, 16:43 |
|
LIMIT, JOIN и использование индексов
|
|||
---|---|---|---|
#18+
Bond_JamesBondНе, нас интересует только "базовый" SQL. И вообщем, то поддержка SQL 2003 - (в 99 - поддержка RECURSIVE CTE, в 2003 - window функции), все остальное - не критично. Вот что-то их я не нашел (хотя может невнимательно искал). Может поделитесь ссылкой?Именно таких функций нет. Но уверен, что есть конструкции-аналоги или специальные предикаты к функциям, которые помогут Вам получить желаемый результат, например: аналог ROW_NUMBER() два типа вычисляемых полей %AFTERHAVING %FOREACH %INLIST FOR SOME и т.д. Помимо прочего для SQL представлены объектные расширения ( Special Features ), позволяющие в большинстве случаев отказаться от JOIN множества таблиц, а также упрощающих работу с полями-коллекциями. PS: посмотрите ещё Caché Transact-SQL (TSQL) Migration Guide . ... |
|||
:
Нравится:
Не нравится:
|
|||
15.03.2012, 18:06 |
|
LIMIT, JOIN и использование индексов
|
|||
---|---|---|---|
#18+
servitLeXa NalBatразве Cache в запросе "select TOP 50 f1 from test.C order by f1" уникализирует выдачу DISTINCT-ом?Если вызвать этот запрос отдельно, то нет - вернутся 50 одинаковых значений. Но в контексте подзапроса для конструкции TOP/ORDER BY действуют специальные оптимизации .не нашел подтверждения в разделе "The TOP Clause" по вашей ссылке. servit &sql(truncate table test.C) for i=1:1:60 &sql(insert into test.C(f1,f2) values(2,10)) for i=1:1:40 &sql(insert into test.C(f1,f2) values(2,1)) for i=1:1:60 &sql(insert into test.C(f1,f2) values(1,10)) for i=1:1:40 &sql(insert into test.C(f1,f2) values(1,1))а что на этих данных выдаст такой запрос select * from test.C where f1 in (select top 2 f1 from test.C order by f1) order by f1,f2 PS: убираю ваше цветное форматирование не со зла. :) а из-за того, что при цитировании текст портится вопросительными знаками. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.03.2012, 18:54 |
|
LIMIT, JOIN и использование индексов
|
|||
---|---|---|---|
#18+
LeXa NalBatа что на этих данных выдаст такой запрос select * from test.C where f1 in (select top 2 f1 from test.C order by f1) order by f1,f2 РезультатIDf1f216111162111631116411165111661116711168111691117011171111721117311174111751117611177111781117911180111811118211183111841118511186111871118811189111901119111192111931119411195111961119711198111991120011101110102110103110104110105110106110107110108110109110110110111110112110113110114110115110116110117110118110119110120110121110122110123110124110125110126110127110128110129110130110131110132110133110134110135110136110137110138110139110140110141110142110143110144110145110146110147110148110149110150110151110152110153110154110155110156110157110158110159110160110 ... |
|||
:
Нравится:
Не нравится:
|
|||
15.03.2012, 22:06 |
|
LIMIT, JOIN и использование индексов
|
|||
---|---|---|---|
#18+
servitLeXa NalBatа что на этих данных выдаст такой запрос select * from test.C where f1 in (select top 2 f1 from test.C order by f1) order by f1,f2Результат ...то есть такой результат опровергает Ваши утверждения "Запрос сперва выберет первые 50 минимальных уникальных значений поля f1" и "Если вызвать этот запрос отдельно, то ... вернутся 50 одинаковых значений. Но в контексте подзапроса для конструкции TOP/ORDER BY ...", так как по-вашему подзапрос "select top 2" выбрал бы два уникальных значения f1 = 1 и 2, и внешний запрос возвратил бы все 200 строк из тестовой таблицы. PS: однако я понял, что мое утверждение о неэквивалентности Вашего запроса исходному не верно. и на моем контр-примере "например в таблице A есть 100 строк с одинаковым минимальным значением f1" Ваш запрос выдаст правильный результат. потому что условию f1 IN ( 1 ) удовлетворяют 100 строк, и они все упорядочатся по (f1,f2), и лишь после этого часть строк отсечется. то есть Ваш запрос правильный. ... |
|||
:
Нравится:
Не нравится:
|
|||
16.03.2012, 00:19 |
|
LIMIT, JOIN и использование индексов
|
|||
---|---|---|---|
#18+
LeXa NalBat , Да, Вы правы: я неточно описал работу первоначального запроса. Под это описание подходит следующий запрос: select top 50 * from test.C where f1 in (select distinct top 50 f1 from test.C) order by f1,f2 select distinct top 50 f1 from test.C Оптимизатор пройдётся по индексу idxF1, который изначально уже отсортирован, отсекая повторяющиеся значения и ограничивая результат до 50 элементов.Цитата из документации по ссылке вышеHowever, Caché applies the DISTINCT and ORDER BY keywords (if specified) before selecting the TOP rows.PS: но в общем случае могут быть ситуации, например, 100млн одинаковых f1, когда один лишь индекс на f1 не поможет. ... |
|||
:
Нравится:
Не нравится:
|
|||
16.03.2012, 11:02 |
|
|
start [/forum/topic.php?all=1&fid=35&tid=1552577]: |
0ms |
get settings: |
10ms |
get forum list: |
13ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
34ms |
get topic data: |
8ms |
get forum data: |
2ms |
get page messages: |
61ms |
get tp. blocked users: |
1ms |
others: | 243ms |
total: | 378ms |
0 / 0 |