Мифы SQL

    Многие разработчики с немалым опытом разработки на любых императивных языках свято верят в то что SQL это тоже самое. Только синтаксис другой. После написания нескольких запросов для вытаскивания данных в свой сервер приложений начинают рождаться мифы о БД.


    У меня примеры написаны и проверенны для Оракла, просто он мне ближе.
    Но тоже самое действительно для любой СУБД.

    UPD: Просили добавить описание что и почему. Добавил.

    1. Магический параметр где-нибудь глубоко в конфигах сервера fast = true.
    2. Скорость работы запроса оценивается по тому как быстро вывелись первые 20 строк.
    3. Можно взять и оптимизировать любой отдельный запрос, или даже часть запроса не трогая ничего кроме него.
    4. Понять как работает запрос и улучшить его можно просто посмотрев на код запроса.
    5. Во временных таблицах не надо делать ни Primary Key, ни индексов.
    6. Внешний ключ = Индекс по полю в дочерней таблице
    7. Запрос с меньшей стоимостью обязан работать быстрее.
    8. Абсолютная идентичность следующих вариантов кода.

    declare
     summ number(10);
     i number(10);
     cursor c is select a from test_pk;
    begin
     summ := 0;
     open c;
     
     loop
      fetch c into i;
      exit when c%notfound;

      summ := summ + i;
     end loop;
     
     close c;
     
     dbms_output.put_line(summ);
     
    end;


    и

    select SUM(a) from table1


    Основное объяснение ведь и там и там просто суммируем, какая разница как именно это делается.

    9. Любое обращение по индексу лучше чем без него.
    9а. И связанное с этим Запрос работает медленно, надо добавить индекс.
    В запросе Full Table Scan по 100 записям, из которых надо 95 и рядом Full Index Scan по миллиону записей из которых надо тоже 95. Все будут 'оптимизировать' Full Table Scan
    10. Скорость соединения таблиц сильно зависит от типов и количества полей по которым мы их соединяем.
    10а. Скорость напрямую зависит от количества таблиц участвующих в запросе.
    11. В запросах вида

    SELECT *
    FROM table t
    Where t.a = 123
    AND t.b = 321


    Всегда будут работать два отдельных индекса по полям а и b.

    Поддержать автора
    Поделиться публикацией

    Похожие публикации

    Комментарии 39

      +22
      Как-то все так сумбурно, я даже не уловил общую мысль :)
        –8
        rtfm
          +2
          Самые частые заблуждения при работе с базами данных. Даже без подробностей, чтобы в тонкости конкретной СУБД не вдаваться.
            –2
            Ясно, перечитал и стало понятнее ) просто сначала как-то не вник
              0
              не осознал. 9а. Разве добавление индекса не ускоряет запрос?
                0
                Смотря какого индекса и смотря какой запрос. Пример из MySQL — сколько ты не добавляй индексы к строковому полю, но если поиск осуществляется REGEXP '...' или LIKE '%...%' (именно с процентом в начале needle) производительности это не прибавит.
                  0
                  Думаю что с REGEXP тоже можно использовать индекс в некоторых случаях (если вначале есть фиксированная часть) так же как с like '...%' :) Хотя данными относительного этого момента не располагаю.
                  Но смысл именно такой — если нет постоянной начальной части строки использование индекса невозможно (вернее все сводится к тому же пробегу по всем записям)
                  +1
                  Смотря какого индекса. Иногда лучше добавить поле к какому то индексу и в результате получить составной индекс. Второй момент добавление индекса может не повлиять на скорость выборки
                  а) если вы используете конструкции в запросе когда использование индекса не возможно (col_name like '%something' или date_add(col_name, 1 minute) = 'some_date' и т.п.)
                  б) данные на которые накладывается индекс имеют частые повторения. к примеру ваше поле хранит 100 уникальных значений и у вас 10 миллионов записей, такой индекс не прибавит вам скорости (конечно все зависит и от распределения значений (если значения равнораспределены то еще будет какой то смысл, иначе может и не быть), и прирост некоторый будет, но не значительный и не тот который мы ожидаем — а скорей всего не будет)
                  в) добавленный индекс может игнорироваться, так как может быть взят другой индекс (совсем не тот что вы ожидаете) — то есть добавляй индекс или не добавляй, он все равно использоваться не будет; выборка записей из одной таблицы осуществляется по одному индексу
                  К тому же добавление нового индекса не всегда хорошо. Новый индекс это дополнительные расходы на UPDATE, INSERT, DELETE и может быть неприемлемо когда у вас производятся частые обновления.

                  Так что добавление индекса это не спасение от всех бед — многое зависит от структуры таблицы, типов данных, структуры данные и самого запроса.
                    0
                    Если правильно выбрать тип индекса — простой, составной, индекс по функции, да еще и не полагаться на оптимизатор, а указать в запросе какой именно индекс использовать, то — ускоряет.
                    Хотя в некоторых случаях — незначительно:)
                      0
                      Это далеко не панацея.
                      Если ускорять каждый запрос создавая именно под него индекс, то мы получим жуткий провал при INSERT или UPDATE по этой таблице.
                      Возможно стоит изменить запрос так чтобы он использовал какой-нибудь из уже существующих индексов, или создать один накрывающий индекс, который пускай не идеально, но подойдет под большинство запросов.
              • НЛО прилетело и опубликовало эту надпись здесь
                  +4
                  Не все СУБД умеют комбинировать индексы, к тому же часто скан одного из индексов с фильтром по второму условию кажется оптимизатору более предпочтительным
                    0
                    Вообще же мне кажется сомнительным мероприятием комбинирование индексов — можем получить неприятную картинку. По сути получается, что мы ищем по нескольким индексам, а потом делаем union? Кажется в таком случае много подводных камней и в редких случаях получится прирост. Можете направить где можно почитать по комбинирование индексов в рабочих СУБД?
                      0
                      Например в случае связывания двух и более таблиц по комбинации полей — составной индекс в каждой из связываемых таблиц по всем полям, участвующим в связке, существенно ускорит выполнение запроса (справедливо для MySQL 5.x). Другой вопрос что такое связывание не совсем нормально, но в некоторых случаях без него не обойтись.
                        +1
                        Вы видимо не поняли. Тут имелось ввиду комбинирование индексов для одной таблицы. То есть имеем таблицу table у которой есть два индекса, так вот в нормальной ситуации большинство (хотя мне казалось все, но может меня поправят) СУБД будут использовать самый длинный индекс, но ОДИН. Автор предыдущего комментария заметил что некоторые СУБД могут принимать решение использовать оба индекса в такой ситуации (то есть что-то вроде искусственного составного индекса, который не был определен для таблицы). Насчет объединения нескольких таблиц — будут использоваться для каждой таблицы свой индекс, какой — уже определит оптимизатор или воспользуется хинтами в самом запросе. Но опять же для каждой таблицы будет использоваться только один индекс.
                          0
                          Именно. Бывает индексы комбинируются, но очень редко.
                          В 95% случаев будет использоваться один индекс с самой большой селективностью.
                        0
                        Извиняюсь за поздний комментарий. Комбинировать можно так называемые bitmap индексы, погуглите про них в oracle. Postgres хотя и не имеет настоящих bitmap-индексов, умеет делать bitmap-сканы — www.postgresql.org/docs/8.3/static/indexes-bitmap-scans.html
                      +1
                      таки там будет лучше работать index(a, b)
                      +12
                      Хоть бы кратко объяснили почему не так. А то ощущение незаконченности какое то :)
                        +1
                        Отдельным топиком только. Кода вставлять очень много надо будет.
                        +6
                        Давайте по порядку:
                        1. FAST = TRUE — на сколько я знаю, на самом деле был такой параметр, только он никак не был связан с разбором SQL
                        2. Явно бред, согласен. Слишком много факторов, которые на это влияют, начиная от хинтов, кончая физическим размещением датафайлов.
                        3. 50 на 50, надо смотреть в первую очередь план, если статистика у вас нормальная.
                        4. При хорошем знании оптимизатора и базы почему нет? Мне, например, для своей базы, достаточно посмотреть на не очень навороченный запрос, чтобы понять будет TAF или нет.
                        5. Смотря зачем вы используете временные таблицы и какой объем данных. Если у вас нужно просто переложить 1000000 записей, потом взять ID и в цикле для них что-то посчитать то зачем индекс??? У вас как минимум будут затраты на заполнение и сортировку индекса. Оно вам надо?
                        6. Внешний ключ ВСЕГДА требует unique index в родительской таблице. Или я не так вас понял?
                        7. Согласен, не всегда.
                        8. Ну и пример… Да… Если человек не видит различий между sql и pl/sql, то его надо тыкать в Concepts до полного усвоения.
                        9. Опять же тыкать в Perfomance Tuning Giude до полного переваривания.
                        Остальное — просто некомпетентность разработчика и непонимания сути индексирования, соединения и вообще принципов sql.
                        Короче надо такие таланты либо гнать, либо учить, это уже вам решать.
                        А вообще двоякое ощущение от топика, вроде бы есть что-то осмысленное, а с другой стороны столько спорных утверждений, что начинаешь сомневаться в компетентности автора, не в обиду будет сказано…
                          +1
                          > 1. FAST = TRUE — на сколько я знаю, на самом деле был такой параметр, только он никак не был связан с > разбором SQL
                          Опа, это такой есть?

                          > 3. 50 на 50, надо смотреть в первую очередь план, если статистика у вас нормальная.
                          Статистика для большинства это вообще нечто из разряда фантастики :)

                          > 4. При хорошем знании оптимизатора и базы почему нет? Мне, например, для своей базы, достаточно > посмотреть на не очень навороченный запрос, чтобы понять будет TAF или нет.
                          Ага, при хорошем знании базы. Если базу хорошо знаешь таких вопросов даже не появляется.
                          Чаще бывает:
                          — Вот запрос в моем приложении тормозит. Как его переписать?

                          > 5.…
                          Я и не говорю что всегда надо. Но никто же никогда вообще не делает. Несмотря на то как временная таблица используется.

                          >6. Внешний ключ ВСЕГДА требует unique index в родительской таблице. Или я не так вас понял?
                          Я про индекс в дочерней вообще-то.
                            0
                            1. Теперь нет. Последний раз он был в районе 6-7 версии, я этого уже не застал.
                            5 непонятно тогда, что вы написали в оригинале: «5. Во временных таблицах не надо делать ни Primary Key, ни индексов.» — если это миф, то почему сейчас вы говорите, что их вообще никто не использует? :)
                            6. Значит я неверно понял.

                            Ну а про все остальное — это просто недостаточная квалификация ваших сотрудников.
                            Уж поверьте мне, и «профи» пишут такие update-ы, что по 2 Тб (это не опечатка, именно террабайт) redo убивают. Так что и не стоит сильно расстраиваться. Просто надо либо увольнять, либо учить ;)

                            PS пример с select sum() очень уж жесткий…
                              0
                              5.
                              Действительно. Плохо сформулировал.
                              Надо бы так: «Никто не задумывается ни о PK, ни об индексах во временных таблицах»

                              Учить, учить и еще учить. Что еще делать :)

                              Пример select sum() из реальной жизни взят. Только там формула расчета результата посложнее была. Но по сути дела тоже самое.
                                0
                                Может вам аутсорсеры нужны?
                                Я б вам наваял что-нить :)
                          0
                          Забыл спросить, почему топик не в блоге SQL? Может перенесете???
                            +3
                            На самом деле пропущен миф номер 0.

                            0. Существует в природе некий язык SQL. — и он базируется на реляционной алгебре.

                            Из этого заблуждения (вернее двух связанных заблуждений) рождаются все остальные. Многие ожидают что SQL ведёт себя как C++ или Java: ты пишешь нечто основываясь на формальной модели и можешь ожидать что реализация A будет вести себя примерно как реализация B. В принципе можно вообще отвлечься от реализации — и получить пусть не блестящий, но вполне хороший результат. В случае с Java ты можешь ожидать что, скажем, сериализация в Sun Java какие-то операции будут быстрее чем в GCJ, а какие-то медленнее, но это будут проценты, в худшем случае разы. В случае с C++ разница вообще редко 2x достигает. В случае с SQL'ем может быть так, что Oracle выполнит запрос за миллисекунду, а MySQL будет работать день. Или наоборот (что, впрочем, случается реже). Нужно примерно знать как это всё устроено внутри, какой путь проделывает ваш запрос и т.д. и т.п.

                            Короче говоря лучше воспринимать SQL как английский или русский: для обращения к Васе, Пете и Тане вроде как можно использовать один и тот же язык — но вот результат обращения гораздо больше зависит от знания вами личностей Васи, Пети и Тани, чем от знания вами языка. Если, конечно, вы просите их сделать что-то мало-мальски нетривиальное… А реляционная алгебра — это учебник грамматики языка: в реальном мире никто не говорит так, как там написано…
                              0
                              Опять из вики, туда писало НЛО:

                              Вопреки существующим заблуждениям, SQL является информационно-логическим языком, а не языком программирования.

                              SQL основывается на реляционной алгебре.
                              0
                              Это описаны пункты, когда говорящий ошибается?
                                0
                                Прочитайте еще раз имя топика
                                0
                                Скомкано как-то, с опечатками, но суть понятна.
                                  –3
                                  «Многие разработчики с немалым опытом разработки на любых императивных языках свято верят в то что SQL это тоже самое. Только синтаксис другой»

                                  Хм… всегда так думал, идем в Вики и что мы видим:
                                  ru.wikipedia.org/wiki/SQL

                                  Независимость от конкретной СУБД:
                                  Несмотря на наличие диалектов и различий в синтаксисе, в большинстве своём тексты SQL-запросов, содержащие DDL и DML, могут быть достаточно легко перенесены из одной СУБД в другую. Существуют системы, разработчики которых изначально закладывались на применение по меньшей мере нескольких СУБД (например: система электронного документооборота Documentum может работать как с Oracle Database, так и с Microsoft SQL Server и IBM DB2)

                                  Наличие стандартов:
                                  Наличие стандартов и набора тестов для выявления совместимости и соответствия конкретной реализации SQL общепринятому стандарту только способствует «стабилизации» языка.

                                  Декларативность:
                                  С помощью SQL программист описывает только то, какие данные нужно извлечь или модифицировать. То, каким образом это сделать решает СУБД непосредственно при обработке SQL запроса.
                                    0
                                    Это все хорошо в теории. На практике разработка под несколько разных СУБД означает разработку разных БД.
                                    Почти весь код переписывать приходится. Отличия незначительные только на первый взгляд.
                                      0
                                      Нет, это понятно, просто различная реализация самих СУБД, и некоторые субд решают одни и теже вещи по разному, та даже взять разные типы таблиц в одном MySQL
                                        0
                                        Ну и зачем тогда постить комментарии о «Независимости от конкретной СУБД»?
                                        Если сами знаете что это не так?
                                          0
                                          Потому что это уже проблемы самих СУБД, и насколько они качественно подошли к выполнению инструкций…

                                          И еще скажите что SELECТ * FROM table сложно перенести, или работу с JOIN, или еще какие-то, и вопрос не только в том что СБУД глупые

                                          Вы всегда руководствуетесь инструкциями именно SQL при написании запросов? Всегда хочется воспользоваться преимуществами (надстройками) той или иной СУБД, вот и вы выбираете ту или иную СУБД с ее преимуществами…

                                          Сам SQL остается один и тот же, изменяется только то как вы его используете…
                                            0
                                            Вы много видели проектов написанных именно на чистом ANSI SQL?

                                            Всегда и везде используются расширения языка, просто потому что это удобно. Сильно ускоряется процесс разработки, упрощается код, улучшается производительность.

                                            Неизвестно даже что проще. Сделать 2 версии заточенные под конкретные СУБД или одну но совместимую со всем.

                                            А мифическая переносимость нужна очень редко. Какому нормальному человеку потребуется зачем-то менять один сервер на другой?
                                              +1
                                              Ну так же можно расуждать и о ООП и о подержке CSS 2(3) и о JasaScript браузерами.
                                              Да я согласен что из за собственых наворотов СУБД переносимость свелась к 0…
                                              Но SQL есть SQL это просто описание как должно быть…

                                              Спс за дискусию :)
                                            0
                                            Речь шла о независимости приложения от СУБД, и это вполне уместно.
                                            Приложение (при соответствующей архитектуре) вполне комфортно переживет смену источника данных — за него отдувается драйвер СУБД на клиенте и хранимые процедуры на сервере.

                                    Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                    Самое читаемое