|
|
|
Как ускорить выборку
|
|||
|---|---|---|---|
|
#18+
Есть информация следующего типа: Код: plaintext 1. 2. 3. 4. 5. 6. Так выглядит БД с 3-мя таблицами MyISAM: Код: 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. Данные нужно вывести по изменению значения у ФИО. Т.е. для приведённой таблицы данные результат выглядит так: Код: plaintext 1. 2. 3. Запрос выглядит так ( http://www.sql.ru/forum/1021188/ne-poymu-kak-sostavit-zapros-i-vozmozhno-li): Код: plsql 1. 2. 3. 4. 5. При количестве записей больше 10 тыс. время выполнения запроса составляет около 4 мин, что слишком долго. Как можно организовать БД по-другому, чтобы ускорить выполнение запроса? Или составить запрос по-другому? Ещё непонятно следующее: у меня первичный ключ в таблице param по (dtime, id_person). Я думал, что это означает, что данные уже хранятся в отсортированном виде по времени и id_person. А значит строчка order by t2.dtime в запросе не нужна. Но без неё запрос выполняется неправильно. Почему? Во вложении архив со скриптом с 11 тыс. данными. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.08.2013, 14:56:52 |
|
||
|
Как ускорить выборку
|
|||
|---|---|---|---|
|
#18+
ObsessЕсть информация следующего типа: Тема ФИО Время ЗначениеПлита Иванов 2013-09-12 14:25:01 234Плита Иванов 2013-09-12 14:25:02 234Плита Иванов 2013-09-12 14:25:03 234Плита Иванов 2013-09-12 14:25:04 235Плита Иванов 2013-09-12 14:25:05 235Плита Петров 2013-09-12 14:25:01 234Вы свой дамп видели? Где там кириллица? Где там дата? ваши данные выглядят вот так: valdtimeid_personid_param436902654789145114369013869116721243690138691167313436901386911674144369013869116751543690138691167616436901386911677174369013869116781843690138691167919436901386911680110 И одно с другим хреновенько соотносится - даже порядок полей иной. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.08.2013, 15:26:46 |
|
||
|
Как ускорить выборку
|
|||
|---|---|---|---|
|
#18+
AkinaВы свой дамп видели? Где там кириллица? Где там дата? Код: plsql 1. При выводе отобразить это можно в виде даты FROM_UNIXTIME(). Хранить лучше в виде числа. Какая разница кириллица или латиница? От этого запрос изменится? AkinaИ одно с другим хреновенько соотносится - даже порядок полей иной. Данные в таблице приведены как пример. Я думаю, запрос к таблице и суть вопроса ( как ускорить запрос? ) не меняется из-за другого порядка полей в таблице и от того кириллица там или японский алфавит. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.08.2013, 17:04:36 |
|
||
|
Как ускорить выборку
|
|||
|---|---|---|---|
|
#18+
ObsessAkinaИ одно с другим хреновенько соотносится - даже порядок полей иной. Данные в таблице приведены как пример. Я думаю, запрос к таблице и суть вопроса ( как ускорить запрос? ) не меняется из-за другого порядка полей в таблице и от того кириллица там или японский алфавит. Не, я понимаю, пятница и всё такое... но всё-таки... Ладно, ФИО == id_person, Время == dtime, Значение == val... но, блин, чё за id_param и куда девалать Тема? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.08.2013, 17:08:37 |
|
||
|
Как ускорить выборку
|
|||
|---|---|---|---|
|
#18+
AkinaЛадно, ФИО == id_person, Время == dtime, Значение == val... но, блин, чё за id_param и куда девалать Тема? БД состоит из 3 таблиц: в одной содержится ФИО (person), во второй Тема (theme), в третьей Параметры (param). id_param добавлен в таблицу param для того, чтобы привести её к нормальной форме . ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.08.2013, 19:08:29 |
|
||
|
Как ускорить выборку
|
|||
|---|---|---|---|
|
#18+
ObsessБД состоит из 3 таблиц: в одной содержится ФИО (person), во второй Тема (theme), в третьей Параметры (param).Т.е. значимая таблица - первая, остальные - просто словари, и могут присоединяться не вначале, а на конечной стадии, когда вся обработка завершена. Obsessid_param добавлен в таблицу param для того, чтобы привести её к нормальной форме.Нормальная форма нахрен тут не нужна. А вот то, что теперь значение этого поля заменит файлово-ориентированную позиционность - ценно. С учётом этого мы можем поставить задачу для себя. Будем считать группой набор записей такой, что у всех записей совпадают значения val и id_person, и эта пара одинакова для любого id_param в пределах от минимального до максимального значения в группе. Вот для каждой такой группы нужно вывести запись с минимальным id_param. Еслит бы пара не повторялась (в группе не было разрывов), всё было бы просто: Код: sql 1. 2. 3. Увы... значит, надо вычленять эти смены. Группа начинается тем id_person, для которого у предыдущего id_person (минус один) значение этой пары иное, и кончается тем id_person, для которого иное значение у следующего id_person (плюс один соответственно). Что приятно - так это то, что неравенство, так что и на самых краях (где id_person-1 или id_person+1) в таблице отсутствуют, соответственно null, сравнение с ним всё равно даёт false. Увы, поздно, нет времени дописАть... завтра. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.08.2013, 22:07:52 |
|
||
|
Как ускорить выборку
|
|||
|---|---|---|---|
|
#18+
Так, продолжим. Во-первых, запрос исходного поста. Немножко подкорректированный в части вывода... чтобы посмотреть поподробнее на результат, а заодно получить сравнение быстродействия систем. Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. Выполнение 5 минут - сравнимо. Любопытно тут - id_param. Чтобы понять, что именно любопытно, делаем тривиальное Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. Забавно - самая первая запись представляет собой самостоятельную группу... причём из-за сортировки по dtime... интересно, так и должно быть? Ну да ладно. А вот дальше - начнём искать те самые границы. Для чего попробуем вот что: Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. Несмотря на три копии, отрабатывает очень быстро. Правда, пропускает ту самую группу из одной записи. Попробуем это исправить, добавив условие увеличения dtime Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. Во-о-от... время видишь? мухой летит... Теперь спокойненько режь эту ерунду на 2 запроса - один ищет начала диапазонов, второй концы, затем линкуй их и находи границы... Ну в общем должно полететь. А мне уже лениво стало. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.08.2013, 21:20:32 |
|
||
|
Как ускорить выборку
|
|||
|---|---|---|---|
|
#18+
Akina, огромное спасибо. Только есть ещё вопрос. Записи в таблицу необязательно вставляются в хронологическом порядке. Если посмотреть таблицу из следующих трёх записей: Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. То, запрос Код: sql 1. 2. 3. 4. 5. 6. 7. выдаст следующую таблицу: Код: sql 1. 2. 3. 4. 5. 6. 7. 8. Хотя значение не менялось и id_person у всех одинаковый. И такое в таблице будет встречаться много раз. Может использовать триггер, чтобы при вставке в таблицу большему значению времени всегда соответствовало большее значение id_param? Количество записей в таблице будет примерно 100 тыс. в месяц для каждой id_theme. Во вложении пример с 3-мя записями. В таблице param я поменял primary key( dtime, id_person)->primary key(id_person, dtime). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.09.2013, 14:39:56 |
|
||
|
Как ускорить выборку
|
|||
|---|---|---|---|
|
#18+
Нет... надо просто попрощаться с использованием поля id_param (да и с самим полем - с последними уточнениями оно вообще получилось нахрен не нужное) и в t?.id_param = t1.id_param ? 1 вместо него использовать dtime . ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.09.2013, 15:16:39 |
|
||
|
Как ускорить выборку
|
|||
|---|---|---|---|
|
#18+
а, не, вру... у тебя же ж там интервалы-то неравномерные... Тогда я бы создал процедуру (см. FAQ), которая пересчитывает это самое поле id_param так, чтобы при id_person_1 = id_person_2 из dtime_1 > dtime_2 однозначно следовало id_param_1 > id_param_2. Т.е. попросту перенумеровать записи в группах по id_person. При этом уникальность id_param в пределах таблицы нафиг не нужна, только в пределах группы. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.09.2013, 15:20:43 |
|
||
|
Как ускорить выборку
|
|||
|---|---|---|---|
|
#18+
Теперь о триггере. Если вставка в таблицу идёт абы как - то да, надо триггер, который будет эту проблему фиксить. Другое дело, что каждый раз, когда что-то летит в таблицу не по порядку, устраивать в триггере перенумерацию - это бредятина. Я бы под это дело завёл служебную табличку. В триггере просто в неё заносил значение id_person, если для него выполняется вставка с нарушением порядка. Эдакий dirty flag. Причём сначала бы проверялось наличие данного id_person в таблице грязных групп, и лишь при отсутствии - нарушение порядка. Если нарушение порядка не обнаружено - присваивал бы полю номера следующее значение, иначе (причём неважно, какое именно иначе) можно оставить пустым. При выборке соответственно смотрел, значится ли нужный id_person в списке грязных, и если да - предварительно выполнял перенумерацию. Причём только для данного id_person. При этом можно использовать и режим "грязной выборки" - т.е. наплевав на последние изменения, которые косые, зато быстро. Плохо, что при этом в триггере фактически выполняется "ручная" генерация уникального для группы ключа. При многопользовательском доступе на корректировку/пополнение данными - будет неприятно... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.09.2013, 15:35:59 |
|
||
|
Как ускорить выборку
|
|||
|---|---|---|---|
|
#18+
Akinaа, не, вру... у тебя же ж там интервалы-то неравномерные... Тогда я бы создал процедуру (см. FAQ), которая пересчитывает это самое поле id_param так, чтобы при id_person_1 = id_person_2 из dtime_1 > dtime_2 однозначно следовало id_param_1 > id_param_2. Т.е. попросту перенумеровать записи в группах по id_person. При этом уникальность id_param в пределах таблицы нафиг не нужна, только в пределах группы. Я создал процедуру. Теперь id_param - порядковый номер dtime в пределах группы и из dtime_1 > dtime_2 однозначно следует id_param_1 > id_param_2. Но выполняется всё равно долго. В таблице 10 тыс. записей. Предыдущий запрос: Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. Твой запрос: Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. Во вложении БД. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.09.2013, 19:19:27 |
|
||
|
Как ускорить выборку
|
|||
|---|---|---|---|
|
#18+
Akina, мне вот ещё непонятно. Ведь у меня есть первичный ключ в таблице param по (id_person, dtime). Разве из этого не следует, что все данные в таблице уже хранятся в упорядоченном виде? Соответсвенно, работать с ними можно как с уже отсортированными. Тогда перенумерация записей: Код: sql 1. не должна ли быть эквивалентна? (без order by ...): Код: sql 1. Таблица MyISAM. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.09.2013, 19:37:19 |
|
||
|
Как ускорить выборку
|
|||
|---|---|---|---|
|
#18+
ScareCrowexplain? Для первого запроса: Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. Для второго запроса: Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.09.2013, 19:47:04 |
|
||
|
Как ускорить выборку
|
|||
|---|---|---|---|
|
#18+
ObsessТвой запрос: Мой? а почему я не в курсе? Obsess Код: sql 1. Код: 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. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.09.2013, 20:54:46 |
|
||
|
|

start [/forum/topic.php?fid=47&msg=38384250&tid=1836114]: |
0ms |
get settings: |
4ms |
get forum list: |
10ms |
check forum access: |
2ms |
check topic access: |
2ms |
track hit: |
49ms |
get topic data: |
8ms |
get forum data: |
2ms |
get page messages: |
53ms |
get tp. blocked users: |
1ms |
| others: | 197ms |
| total: | 328ms |

| 0 / 0 |
