Кластерная индексация в MySQL - PullRequest
0 голосов
/ 19 декабря 2018

Я учусь индексированию в базах данных.Согласно GeeksforGeeks (https://www.geeksforgeeks.org/indexing-in-databases-set-1/), индексный файл создан для кластерного индекса. Существует диаграмма, показывающая индексный файл с семестрами 1-8.

Но при чтении https://use -the-index-luke.com/blog/2014-01/unreasonable-defaults-primary-key-clustering-key, упоминается

Если таблица имеет кластеризованный индекс, это в основном означаетиндексом является таблица

Я хочу знать, генерируется ли индексный файл в кластеризованном индексе и не кластеризованном индексе или нет?

Кроме того, можем ли мы увидеть индексный файл натаблица, т. е. что она хранит?

Ответы [ 3 ]

0 голосов
/ 19 декабря 2018

Я хочу знать, генерируется ли индексный файл в кластеризованном индексе и не кластеризованном индексе или нет?

Таблица InnoDB (тип механизма по умолчанию) в MySQL всегда кластеризована.Это означает, что индекс хранит все столбцы таблицы;нет необходимости в отдельной таблице «кучи».Если бы вы использовали старый движок MyIsam, то у таблицы была бы куча плюс любые дополнительные индексы поверх нее.

Кроме того, мы можем увидеть файл индекса в таблице, то есть чтоон хранит?

«Основной» индекс хранит все столбцы таблицы: ключевые столбцы и неключевые столбцы.«Вторичные» индексы могут быть более избирательными и хранить только подмножество столбцов;но у первичного есть все.

0 голосов
/ 19 декабря 2018

Это дело кластеризованных индексов, с точки зрения пользователя MySQL, является деталью реализации.

Информация в таблице должна храниться где-то на таком устройстве хранения, как SSD или жесткий диск.Многое зависит от версии сервера базы данных и конкретного используемого метода доступа (InnoDB, MyISAM, ...).

Часть информации является метаданными: описание таблицы.MySql часто хранит это в файле table.frm.Информация в строках часто хранится в файле контейнера tablename.ibd.Эти файлы должны интерпретироваться только сервером MySQL или другим программным обеспечением, созданным для этой цели;типичная автономная программа не может понять их , особенно , если сервер MySQL активен.Другими словами: если вы напишите программу для изменения любого из этих файлов, вы испортите вашу базу данных и потеряете содержимое ваших таблиц.

Внутри файлов контейнера находятся некоторые структуры данных, к которым обращается код метода доступа MySQL.Часто таблицы с первичными ключами хранятся так, как если бы они были индексами со всеми данными для каждой строки, свисающими с каждой записи индекса.Эта структура данных является кластеризованным индексом .

Вы не можете обязательно просматривать файловую систему компьютера, на котором работает сервер MySQL, и указывать на конкретный файл, содержащий индекс, или кластерныйиндекс или что-то еще.С InnoDB вы можете указать MySQL поместить данные в определенные файлы в файловую систему, используя команды TABLESPACE .Но в MySQL 8 нет способа поместить индекс в собственное табличное пространство.

(администраторы баз данных для таких продуктов, как Oracle и MS SQL Server Enterprise Edition работают с перемещением табличных пространств на разные диски для оптимизации и распараллеливанияЭто не так уж сложно в MySQL, пока ваши таблицы не начнут занимать значительные доли дискового пространства.)

0 голосов
/ 19 декабря 2018

MySQL имеет по существу один метод индексации: BTree.(Да, есть также Spatial и Fulltext, но это другое обсуждение.)

Как только вы поймете, как работает BTree (см. Википедию), мы можем обсудить, что входит в конечные узлы в InnoDB.

Случай 1: «Дерево данных» BTree содержит все столбцы и сортируется в соответствии с PRIMARY KEY.В MySQL PK имеет значение по определению , "UNIQUE" и "Clustered".(У других поставщиков есть другие варианты.)

Случай 2: «Вторичный» INDEX хранится в отдельном BTree.В конечных узлах находятся (1) столбцы, определенные во вторичном индексе, плюс копии столбцов PK.Чтобы завершить SELECT с использованием вторичного индекса, он должен сначала извлечь PK с использованием индекса BTree, а затем извлечь данные через данные BTree.(Если индекс «покрывает», этот второй шаг не требуется.)

В MySQL не существует «Rownum».

BTrees на самом деле являются деревьями B +, что позволяет выполнять сканирование диапазона.более эффективный.

InnoDB помещает все BTrees для данной таблицы (один для данных + PK, один для каждого вторичного индекса) в некоторое табличное пространство.Табличное пространство является либо общим (ibdata1 файл), либо табличным (файл tablename.ibd), либо (в более новых версиях) файлом «табличного пространства», которое может содержать несколько таблиц.

Предостережение: То, что я описал, относится к InnoDB MySQL и, вероятно, не подходит для любого другого движка.

Я не знаю хорошего инструмента для проверки BTrees InnoDB, не вдаваясь в подробности.Для версии Percona:

SELECT  i.INDEX_NAME as Index_Name,
                IF(ROWS_READ IS NULL, 'Unused',
                    IF(ROWS_READ > 2e9, 'Overflow', ROWS_READ)) as Rows_Read
            FROM (
                SELECT DISTINCT TABLE_SCHEMA, TABLE_NAME, INDEX_NAME
                    FROM information_schema.STATISTICS
                 ) i
            LEFT JOIN information_schema.INDEX_STATISTICS s
                     ON i.TABLE_SCHEMA = s.TABLE_SCHEMA
                    AND i.TABLE_NAME = s.TABLE_NAME
                    AND i.INDEX_NAME = s.INDEX_NAME
            WHERE i.TABLE_SCHEMA = ?
              AND i.TABLE_NAME = ?
            ORDER BY IF(i.INDEX_NAME = 'PRIMARY', 0, 1)

Для MySQL (Oracle):

SELECT  last_update,
                n_rows,
                'Data & PK' AS 'Type',
                clustered_index_size * 16384 AS Bytes,
                ROUND(clustered_index_size * 16384 / n_rows) AS 'Bytes/row',
                clustered_index_size AS Pages,
                ROUND(n_rows / clustered_index_size) AS 'Rows/page'
        FROM mysql.innodb_table_stats
        WHERE ( ( database_name = ? AND table_name = ? )
          OR    ( database_name = LOWER(?) AND table_name = LOWER(?) 
    UNION
        SELECT  last_update,
                n_rows,
                'Secondary Indexes' AS 'BTrees',
                sum_of_other_index_sizes * 16384 AS Bytes,
                ROUND(sum_of_other_index_sizes * 16384 / n_rows) AS 'Bytes/row',
                sum_of_other_index_sizes AS Pages,
                ROUND(n_rows / sum_of_other_index_sizes) AS 'Rows/page'
        FROM mysql.innodb_table_stats
        WHERE ( ( database_name = ? AND table_name = ? )
          OR    ( database_name = LOWER(?) AND table_name = LOWER(?) 
          AND sum_of_other_index_sizes > 0
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...