Новые сообщения [новые:0]
Дайджест
Горячие темы
Избранное [новые:0]
Форумы
Пользователи
Статистика
Статистика нагрузки
Мод. лог
Поиск
|
12.06.2013, 03:23
|
|||
---|---|---|---|
|
|||
Суррогатный ключ медленнее естественного? |
|||
#18+
Доброго времени суток. Требуется помощь умных людей. Изначально спроектировал в БД две таблицы: CREATE TABLE eq (code VARCHAR NOT NULL ON CONFLICT ABORT DEFAULT ('') PRIMARY KEY ASC ON CONFLICT ABORT, parent REFERENCES eq ON UPDATE CASCADE ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE, flag_group BOOLEAN NOT NULL ON CONFLICT ABORT DEFAULT (0), CHECK (parent != code)); CREATE TABLE eq_period (owner NOT NULL ON CONFLICT ABORT REFERENCES eq ON UPDATE CASCADE ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE, date_begin DATE NOT NULL ON CONFLICT ABORT DEFAULT CURRENT_DATE, name VARCHAR, co TEXT, CHECK (name NOT NULL OR co NOT NULL) PRIMARY KEY (owner COLLATE BINARY ASC, date_begin COLLATE BINARY ASC) ON CONFLICT ABORT); Здесь: Tаблица eq многоуровневая. Условно это выглядит так: группы, подгруппы, ..., элементы. Связь между уровнями осуществляется через поля code - parent. Поле code полностью отвечает требованиям PRIMARY KEY. Tаблица eq_period должна содержать значения полей name и co на определённую дату. Связь с таблицей eq осуществляется через поля code - owner. Для выборки записей использую такой SELECT: SELECT t.code, t.parent, t.flag_group, (SELECT max(date_begin) FROM eq_period WHERE owner=t.code AND date_begin<=?) AS date_begin, (SELECT name FROM eq_period WHERE owner=t.code AND date_begin<=? AND name NOT NULL ORDER BY date_begin DESC LIMIT 1) AS name, (SELECT co FROM eq_period WHERE owner=t.code AND date_begin<=? AND co NOT NULL ORDER BY date_begin DESC LIMIT 1) AS co FROM eq AS t WHERE t.parent IS NULL (для 1-го уровня) WHERE t.parent=? (для уровней > 1-го) К слову сказать, мне самому не очень нравиться SELECT-ы в SELECT-е, но добиться нужного результата с помощью JOIN-ов + GROUP BY мне так и не удалось. Похожая тема по поектированию подчинённых таблиц для периодических значений здесь на форуме вроде уже поднималась. Если есть более интересные варианты, буду признателен за ссылочку. Результатом SELECT-а должна быть таблица, каждая запись которой содержит (помимо кода и пр.) значения полей name и co на заданную дату (если таковые имеются, т.е. NOT NULL) или дату, меньшую заданной (-"-). В процессе дальнейшего проектирования очередных таблиц натолкнулся на составные естественные PRIMARY KEY в 3-4 поля. Поэтому было принято решение использовать в этих таблицах суррогатные PRIMARY KEY. Заодно, взвесив все за и против, решил и в первых таблицах подставить суррогатные PRIMARY KEY (id): CREATE TABLE eq (id INTEGER PRIMARY KEY ON CONFLICT ABORT AUTOINCREMENT, parent REFERENCES eq ON UPDATE CASCADE ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE, flag_group BOOLEAN NOT NULL ON CONFLICT ABORT DEFAULT (0), code VARCHAR NOT NULL ON CONFLICT ABORT DEFAULT ('') UNIQUE ON CONFLICT ABORT COLLATE BINARY, CHECK (parent != id)); CREATE TABLE eq_period (id INTEGER PRIMARY KEY ON CONFLICT ABORT AUTOINCREMENT, owner NOT NULL ON CONFLICT ABORT REFERENCES eq ON UPDATE CASCADE ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE, date_begin DATE NOT NULL ON CONFLICT ABORT DEFAULT CURRENT_DATE, name VARCHAR, co TEXT, CHECK (name NOT NULL OR co NOT NULL) UNIQUE (owner COLLATE BINARY ASC, date_begin COLLATE BINARY ASC) ON CONFLICT ABORT); Соответственно и подкорректировал свой основной SELECT. В результате скорость основных операций (вставка, обновление, выборка) упала в разы! Визуально (в программе) это выглядит просто ужасающе: в первом случае переходы в/из группы/подгруппы были мгновенны,- никаких задержек, а во втором - ... можно успеть покурить. Я в тупике. даже не знаю в какую сторону смотреть. Но возвращаться к естественным ключам уже не хочется. Буду рад любой помощи по данному вопросу. Спасибо. P.s. Вдруг понадобиться. Сейчас стоит SQLite версии 3.7.17 (ранее пробовал на 3.5.9). Пользую Python 2.6.6 ... |
|||
:
Нравится:
Не нравится:
|
|||
|
12.06.2013, 10:52
|
|||
---|---|---|---|
Суррогатный ключ медленнее естественного? |
|||
#18+
1. Для вставки кода используйте теги. ... |
|||
:
Нравится:
Не нравится:
|
|||
|
12.06.2013, 13:45
|
|||
---|---|---|---|
Суррогатный ключ медленнее естественного? |
|||
#18+
Воодбще должно быть быстрее с сурагатными ключами. Копайте дальше, возможно ошибка в другом. ... |
|||
:
Нравится:
Не нравится:
|
|||
|
12.06.2013, 13:52
|
|||
---|---|---|---|
|
|||
Суррогатный ключ медленнее естественного? |
|||
#18+
wamacoВоодбще должно быть быстрее с сурагатными ключами. Вот и я так думал. Тем более, что такой суррогатный ключ изначально завязан на rowid, а он по идее самый быстрый. ... |
|||
:
Нравится:
Не нравится:
|
|||
|
12.06.2013, 14:01
|
|||
---|---|---|---|
|
|||
Суррогатный ключ медленнее естественного? |
|||
#18+
wamacoКопайте дальше, возможно ошибка в другом. Так вот я и не понимаю в чём. В обоих случаях запросы одинаковые, настройки я не менял. Единственное, во 2-м случае при вставке записей на каждую из записей выполняется на 1 SELECT больше, чем в 1-м случае, - для поиска parent-а или owner-а. А при выборке запросы идентичные. ... |
|||
:
Нравится:
Не нравится:
|
|||
|
12.06.2013, 14:16
|
|||
---|---|---|---|
Суррогатный ключ медленнее естественного? |
|||
#18+
Alzheimer, поиграйте с индексами. что-то такое подозрение что-то там. у себя проверил. такого не наблюдается. решите, отпишитесь пожалуйста. интересно даже стало. ... |
|||
:
Нравится:
Не нравится:
|
|||
|
12.06.2013, 15:25
|
|||
---|---|---|---|
|
|||
Суррогатный ключ медленнее естественного? |
|||
#18+
Вот результаты EXPLAIN QUERY PLAN: 1 selectid,order,from,detail 0,0,0,SCAN TABLE eq AS t (~500000 rows) 0,0,0,EXECUTE CORRELATED SCALAR SUBQUERY 1 1,0,0,SEARCH TABLE eq_period USING COVERING INDEX sqlite_autoindex_eq_period_1 (owner=? AND date_begin<?) (~1 rows) 0,0,0,EXECUTE CORRELATED SCALAR SUBQUERY 2 2,0,0,SEARCH TABLE eq_period USING INDEX sqlite_autoindex_eq_period_1 (owner=? AND date_begin<?) (~2 rows) 0,0,0,EXECUTE CORRELATED SCALAR SUBQUERY 3 3,0,0,SEARCH TABLE eq_period USING INDEX sqlite_autoindex_eq_period_1 (owner=? AND date_begin<?) (~2 rows) 2 selectid,order,from,detail 0,0,0,SCAN TABLE eq AS t (~500000 rows) 0,0,0,EXECUTE CORRELATED SCALAR SUBQUERY 1 1,0,0,SEARCH TABLE eq_period USING COVERING INDEX sqlite_autoindex_eq_period_1 (~1 rows) 0,0,0,EXECUTE CORRELATED SCALAR SUBQUERY 2 2,0,0,SCAN TABLE eq_period (~16666 rows) 2,0,0,USE TEMP B-TREE FOR ORDER BY 0,0,0,EXECUTE CORRELATED SCALAR SUBQUERY 3 3,0,0,SCAN TABLE eq_period (~16666 rows) 3,0,0,USE TEMP B-TREE FOR ORDER BY Я правильно понимаю, в случае с суррогатным ключом таблица eq_period сканируется без условия owner=? AND date_begin<? ? ... |
|||
:
Нравится:
Не нравится:
|
|||
|
12.06.2013, 16:36
|
|||
---|---|---|---|
|
|||
Суррогатный ключ медленнее естественного? |
|||
#18+
wamacoпоиграйте с индексами. что-то такое подозрение что-то там. Вроде так и есть. Как я понял, в 1-м случае подзапросы делают выборку сначала по PRIMARY KEY (owner + date_begin), затем по name (co соответственно). А во 2-м случае UNIQUE-индекс для поиска name и co вообще не используется,- вот отсюда и тормоза, сплошной перебор всех записей. Возникает вопрос: почему UNIQUE-индекс "не поднимается", как PRIMARY KEY-индекс? ... |
|||
:
Нравится:
Не нравится:
|
|||
|
13.06.2013, 14:29
|
|||
---|---|---|---|
|
|||
Суррогатный ключ медленнее естественного? |
|||
#18+
Если интересно, разобрался я с этой бедой. Всё заработало после того, как полю owner из таблицы eq_period был явно присвоен тип INTEGER. Т.е. просто указания ссылки REFERENCES eq не хватало!? Странное дело, т.к. полю parent из таблицы eq вполне хватает ссылки, тип явно не указан. Самое интересное, что DDL таблиц, созданный из кода программы, трактуется в разных менеджерах по-своему. Для тестирования, помимо своей программы, ещё использую менеджеры SQLite Expert Professional и SQLite Studio. Так вот в SQLite Expert Professional заметил такой косяк (уж не знаю это косяк менеджера или самого sqlite): у индекса PRIMARY KEY (поле id) таблицы eq нет имени, а AUTOINCREMENT не включён; индекс UNIQUE (поле code) имеет имя sqlite_autoindex_eq1 и не поддаётся редактированию, => работает он или нет - неизвестно. При попытке включить AUTOINCREMENT индексу поля id, индекс поля code самоудаляется. Разве индексы AUTOINCREMENT PRIMARY KEY и UNIQUE не могут нормально сосуществовать в одной таблице? После решения этих вопросов возникло ещё больше вопросов))) Если есть мнения по этому поводу, поделитесь, пожалуйста. ... |
|||
:
Нравится:
Не нравится:
|
|||
|
13.06.2013, 22:43
|
|||
---|---|---|---|
|
|||
Суррогатный ключ медленнее естественного? |
|||
#18+
AlzheimerЕсли есть мнения по этому поводу, поделитесь, пожалуйста. Используйте sqlite3 шелл - как минимум, для проверки, и вопросов станет меньше. Мало ли что могут наворотить различные сторонние оболочки для управления базами... ... |
|||
:
Нравится:
Не нравится:
|
|||
|
14.06.2013, 02:29
|
|||
---|---|---|---|
Суррогатный ключ медленнее естественного? |
|||
#18+
AlzheimerСамое интересное, что DDL таблиц, созданный из кода программы, трактуется в разных менеджерах по-своему.Потому что это никакие не менеджеры, а самостоятельные СУБД с собственным движком базы данных. Каждый sqlite3.dll находящийся у тебя на машине это отдельный независимый от других движок базы. В каждом могут быть включены или выключены какие-либо опции и возможности. Про разные версии уж и говорить не нужно. Когда ты открываешь свою базу программой которая использует один sqlite3.dll, а потом другой программой которая использует другой sqlite3.dll, то ты сильно рискуешь порушить свой файл базы. А еще бывают программы которые не используют внешний sqlite3.dll а содержат весь движок базы внутри своего .exe (или собственной .dll). И тогда, открытие файлов базы от этой программы в сторонних "менеджерах" это верный способ убить базу. Потому что статическую линковку чаще всего делают тогда, когда нужны некие специфические опции компиляции движка и специально не хотят чтобы слишком умелый юзер подсовывал в программу чужую sqlite3.dll. ... |
|||
:
Нравится:
Не нравится:
|
|||
|
|
start [/forum/topic.php?fid=54&mobile=1&tid=2008897]: |
0ms |
get settings: |
12ms |
get forum list: |
15ms |
check forum access: |
5ms |
check topic access: |
5ms |
track hit: |
29ms |
get topic data: |
12ms |
get forum data: |
3ms |
get page messages: |
55ms |
get tp. blocked users: |
2ms |
others: | 272ms |
total: | 410ms |
0 / 0 |