Mysql int vs varchar как первичный ключ (InnoDB Storage Engine?

Я создаю веб-приложение (систему управления проектами), и мне было интересно об этом, когда дело дошло до производительности.

У меня есть таблица «Проблемы», внутри которой есть 12 внешних ключей, связанных с различными другими таблицами. из них, 8 из них, мне нужно будет присоединиться, чтобы получить поле заголовка из других таблиц, чтобы запись имела смысл в веб-приложении, но затем означает выполнение 8 объединений, которые кажутся чрезмерно чрезмерными, особенно, поскольку я только затягиваю 1 для каждого из этих объединений.

Теперь мне также сказали использовать первичный ключ с автоматическим добавлением (если только очертание не является проблемой, в этом случае я должен использовать GUID) по причинам постоянства, но насколько плохо использовать переменную varchar (максимальная длина 32) ? Я имею в виду, что большинство этих таблиц, вероятно, не будет иметь много записей (большинство из них должны быть ниже 20). Также, если я использую заголовок в качестве основного ключа, мне не придется делать присоединение в 95% случаев, поэтому для 95% sql я бы даже попал в любой хит производительности (я думаю). Единственный недостаток, который я могу придумать, - это то, что у меня будет больше дискового пространства (но в день это действительно большое дело).

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

Каковы недостатки использования varchar в качестве первичного ключа для таблицы, за исключением того, что у нее много записей?

ОБНОВЛЕНИЕ - Некоторые тесты

Поэтому я решил сделать некоторые базовые тесты на этом материале. У меня 100000 записей, и это базовые запросы:

База VARCHAR FK Query

SELECT i.id, i.key, i.title, i.reporterUserUsername, i.assignedUserUsername, i.projectTitle, 
i.ProjectComponentTitle, i.affectedProjectVersionTitle, i.originalFixedProjectVersionTitle, 
i.fixedProjectVersionTitle, i.durationEstimate, i.storyPoints, i.dueDate, 
i.issueSecurityLevelId, i.creatorUserUsername, i.createdTimestamp, 
i.updatedTimestamp, i.issueTypeId, i.issueStatusId
FROM ProjectManagement.Issues i

База INT FK Query

SELECT i.id, i.key, i.title, ru.username as reporterUserUsername, 
au.username as assignedUserUsername, p.title as projectTitle, 
pc.title as ProjectComponentTitle, pva.title as affectedProjectVersionTitle, 
pvo.title as originalFixedProjectVersionTitle, pvf.title as fixedProjectVersionTitle, 
i.durationEstimate, i.storyPoints, i.dueDate, isl.title as issueSecurityLevelId, 
cu.username as creatorUserUsername, i.createdTimestamp, i.updatedTimestamp, 
it.title as issueTypeId, is.title as issueStatusId
FROM ProjectManagement2.Issues i
INNER JOIN ProjectManagement2.IssueTypes `it` ON it.id = i.issueTypeId
INNER JOIN ProjectManagement2.IssueStatuses `is` ON is.id = i.issueStatusId
INNER JOIN ProjectManagement2.Users `ru` ON ru.id = i.reporterUserId
INNER JOIN ProjectManagement2.Users `au` ON au.id = i.assignedUserId
INNER JOIN ProjectManagement2.Users `cu` ON cu.id = i.creatorUserId
INNER JOIN ProjectManagement2.Projects `p` ON p.id = i.projectId
INNER JOIN ProjectManagement2.`ProjectComponents` `pc` ON pc.id = i.projectComponentId
INNER JOIN ProjectManagement2.ProjectVersions `pva` ON pva.id = i.affectedProjectVersionId
INNER JOIN ProjectManagement2.ProjectVersions `pvo` ON pvo.id = i.originalFixedProjectVersionId
INNER JOIN ProjectManagement2.ProjectVersions `pvf` ON pvf.id = i.fixedProjectVersionId
INNER JOIN ProjectManagement2.IssueSecurityLevels isl ON isl.id = i.issueSecurityLevelId

Я также выполнил этот запрос со следующими дополнениями:

  • Выберите конкретный элемент (где i.key = 43298)
  • Группа i.id
  • Сортировать по (it.title для int FK, i.issueTypeId для varchar FK)
  • Предел (50000, 100)
  • Группировка и ограничение вместе
  • Группировка, порядок и ограничение вместе

Результаты для них, где:

  

QUERY TYPE: VARCHAR FK TIME /INT FK TIME

     

Базовый запрос: ~ 4 мс /~ 52 мс

     

Выберите конкретный элемент: ~ 140 мс /~ 250 мс

     

Группа по i.id: ~ 4ms /~ 2.8sec

     

Сортировать по: ~ 231ms /~ 2sec

     

Предел: ~ 67 мс /~ 343 мс

     

Группировка и ограничение вместе: ~ 504 мс /~ 2 сек

     

Группировка, порядок и ограничение вместе: ~ 504 мс /~ 2,3 секунды

Теперь я не знаю, какую конфигурацию я мог бы сделать, чтобы сделать тот или другой (или оба) быстрее, но кажется, что VARCHAR FK быстрее просматривает запросы для данных (иногда намного быстрее).

Думаю, мне нужно выбирать, будет ли это повышение скорости дополнительным размером данных /индекса.

12 голосов | спросил ryanzec 31 MarpmSat, 31 Mar 2012 14:25:47 +04002012-03-31T14:25:47+04:0002 2012, 14:25:47

1 ответ


1

В дополнение к ответу @atxdba - который объяснил вам, почему использование числового будет лучше для дискового пространства, я хотел бы добавить две точки:

  1. Если ваша таблица проблем основана на VARCHAR FK, и предположим, что у вас есть 20 небольших VARCHAR (32) FK, ваша запись может достигать длины 20x32 байта, тогда как ваши упоминания о других таблицах являются поисковыми таблицами, поэтому INT FK может быть TINYINT FK, который делает для 20 полей 20-байтовыми записями. Я знаю, что за несколько сотен записей это не изменится, но когда вы доберетесь до нескольких миллионов, я думаю, вы по достоинству оцените экономию пространства.

  2. Для решения проблемы скорости я бы рассмотрел использование индексов покрытия, поскольку, по-видимому, для этого запроса вы не извлекаете столько данных из таблиц поиска, я бы пошел на покрытие индекса и повторю тест, который вы предоставили с помощью VARCHAR FK /W /COVERING INDEX И обычный INT FK.

Надеюсь, что это поможет,

ответил Spredzy 2 AMpMon, 02 Apr 2012 10:19:35 +040019Monday 2012, 10:19:35

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132