MySQL Большие таблицы управления? - PullRequest
0 голосов
/ 15 сентября 2011

Мне нужно сделать эту реализацию:

enter image description here

Я использую Php и MySQL. Как видите, цены могут быть динамически построены. Чтобы выполнить это требование, я создал следующую схему:

`tbl_states` (id, state)
`tbl_prices` (id, price)
`tbl_years`  (id, year)
`tbl_states_prices` (id, state_id, customer_id, year_id, price_id, value)

Значения для каждой цены будут сохранены в tbl_states_prices. Значения зависят от государства, клиента и года. Меня беспокоит размер этой таблицы, поскольку максимальное количество лет - 20, цены - около 6, а среднее количество клиентов - 300.

Я не знаю, каковы последствия использования этой схемы. Как мне управлять этой таблицей? Разбить на маленькие столики для каждого клиента? Просмотры? Отсутствие у меня опыта работы с базами данных мне не помогает. Предложения будут оценены.

Ответы [ 3 ]

1 голос
/ 15 сентября 2011

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

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

Для каждой пары покупателя и продавца мы сохраняем уникальные расходы (прогноз). Один заряд принадлежит только одному клиенту.

Год1, год2 поля нет, год должен быть одним полем, не много полей. А также потому что это поле с множеством вхождений (аналогично случаю с телефоном) хорошая практика требует другого стола, чтобы помочь нам. Так что нет такой вещи, как динамические поля, поля статичны, как камень, фундаментальное правило! Кроме того, если мы говорим о действительно огромных данных (что я не думаю, что мы могли бы разбить таблицу сборов на части, относящиеся к определенному году, например, но это требует больше работы).
Очень важная вещь ... у вас может быть определенный способ думать представить эти данные, год 1, год 2 и т. д. по горизонтали, по вертикали .. однако вы никогда пусть эти идеи вмешиваются в вашу реляционную диаграмму, визуальное отображение (может измениться в любое время) и дизайн должен быть отдельным.

Что касается штатов, есть небольшая хитрость, чтобы сохранить поле маленьким, что означает более быструю работу и опуская таблицу состояний. Для этого требуется простая функция php, которая при задании состояния например, в Калифорнии хранится миниатюра вместо Калифорнии. Или вы можете сохранить таблица состояний с ее идентификатором tinyint передается в качестве внешнего ключа в таблицу сборов. Выбирай, что хочешь.

/ Сущность является обобщением для Продавца и Клиента. Обобщение необходимо обрабатывать аналогичные поля, например, для розничного продавца и клиента есть адрес электронной почты, адрес и т. д. С другой стороны, клиент и продавец спецификация объекта, он нам нужен для обработки полей, которые отличаются например, нам все равно, женат ли ретейлер! /

Ниже приведен только пример.

drop table if exists `Entity_Phone`;
drop table if exists `Retailer_Customer`;
drop table if exists `Charge`;
drop table if exists `Retailer`;
drop table if exists `Customer`;

drop table if exists `Entity`;
  CREATE TABLE `Entity` (
  `entity_id` INT UNSIGNED NOT NULL   AUTO_INCREMENT,
  /*example code 0 is for retailer and code 1 is for customer*/
  `entity_code` tinyint not null,
  `entity_other_field` VARCHAR(30) NOT NULL,
  PRIMARY KEY  (`entity_id`)
) ENGINE=InnoDB   DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT;
/*You don't have to use utf8 if not needed*/

/*Phone number, instead of only phone you can store more info
like multiple emails etc, just change the table name to  make sense,
the datatype and in the php function that associates codes add 
as many codes needed*/
CREATE TABLE `Entity_Phone` (
  `entity_id` INT UNSIGNED NOT NULL  ,
  `phone` BIGINT UNSIGNED NOT NULL  ,
  /*code 1 is for fix phone, 2 is for mobile phone and 3 for fax*/
  `identification_code`  TINYINT UNSIGNED DEFAULT '1' NOT NULL,
  PRIMARY KEY  (`entity_id`),
  CONSTRAINT `fk1EntData` FOREIGN KEY (`entity_id`)
        REFERENCES `Entity` (`entity_id`)
        ON DELETE CASCADE
) ENGINE=InnoDB ROW_FORMAT=COMPACT;


  CREATE TABLE `Retailer` ( 
  `retailer_fname` VARCHAR(30) NOT NULL,
  `retailer_lname` VARCHAR(30) NOT NULL,
  /*pkey directly shared from entity table, just with a different name*/
  `retailer_id` INT UNSIGNED NOT NULL ,
  PRIMARY KEY  (`retailer_id`),
  CONSTRAINT `fk1RetEnt` FOREIGN KEY (`retailer_id`)
        REFERENCES `Entity` (`entity_id`)
        ON DELETE CASCADE
) ENGINE=InnoDB   DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT;

  CREATE TABLE `Customer` ( 
  `customer_fname` VARCHAR(30) NOT NULL,
  `children_number` tinyint not null,
   `customer_id` INT UNSIGNED NOT NULL ,
  PRIMARY KEY  (`customer_id`),
   CONSTRAINT `fk1CustData` FOREIGN KEY (`customer_id`)
        REFERENCES `Entity` (`entity_id`)
        ON DELETE CASCADE
) ENGINE=InnoDB   DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT;



CREATE TABLE `Retailer_Customer` ( 
  `customer_id` INT UNSIGNED NOT NULL  ,
  `retailer_id` INT UNSIGNED NOT NULL  ,   
  PRIMARY KEY  (`customer_id`,`retailer_id`),
  CONSTRAINT `fk1RetCust` FOREIGN KEY (`customer_id`)
        REFERENCES `Entity` (`entity_id`)
        ON DELETE CASCADE, 
 CONSTRAINT `fk2RetCust` FOREIGN KEY (`retailer_id`)
        REFERENCES `Entity` (`entity_id`)
        ON DELETE CASCADE

) ENGINE=InnoDB ROW_FORMAT=COMPACT;




/*
if you want to keep the state table... for example you might need to store 
information for states so you need this table to keep those fields
CREATE TABLE `State` (
  `state_id` tinyINT UNSIGNED NOT NULL  ,
  `state_name` varchar(50) not null ,  
  PRIMARY KEY  (`state_id`),
  unique(`state_name`) 
) ENGINE=InnoDB ROW_FORMAT=COMPACT;
*/
CREATE TABLE `Charge` ( 
  `retailer_id` INT UNSIGNED NOT NULL  ,
   `customer_id` INT UNSIGNED NOT NULL  ,
  `state_code` TINYINT UNSIGNED NOT NULL  ,
  /*state  could be stored here directly as 
  varchar however this way it asks less space,
  is faster and allows no orthographical erros 
 on insertion */
  /*`state_id` tinyint UNSIGNED NOT NULL  , if you want the state table*/
    `charge_date_time`  DATETIME  NOT NULL,
  index(`customer_id`),
  PRIMARY KEY  (`retailer_id`,`customer_id`,`charge_date_time`),
  CONSTRAINT `fk1Charge` FOREIGN KEY (`retailer_id`)
        REFERENCES `Retailer` (`retailer_id`)
        ON DELETE CASCADE,
  CONSTRAINT `fk2Charge` FOREIGN KEY (`customer_id`)
        REFERENCES `Customer` (`customer_id`)
        ON DELETE CASCADE 
 /* if you want the state table
 ,CONSTRAINT `fk2pr` FOREIGN KEY (`state_id`)
        REFERENCES `State` (`state_id`)
        ON DELETE CASCADE
*/
) ENGINE=InnoDB ROW_FORMAT=COMPACT;



/*This is how you insert a Retailer*/  
insert into `Entity` (`entity_code`, `entity_other_field`)
  values ('0','test');
insert into `Retailer` (`retailer_fname`, `retailer_lname`,
  `retailer_id`) values ('John', 'Smith',(SELECT LAST_INSERT_ID()));
insert into `Entity_Phone` (`entity_id`, `phone`,`identification_code`) values 
((SELECT LAST_INSERT_ID()), 123222,3);
/****************************************************/


/*This is how you insert a Customer*/ 
insert into `Entity` (`entity_code`, `entity_other_field`)
  values ('1','test');
insert into `Customer` (`customer_fname`, `children_number`,
  `customer_id`) values ('Jimm', 3,(SELECT LAST_INSERT_ID()));
insert into `Entity_Phone` (`entity_id`, `phone`,`identification_code`) values 
((SELECT LAST_INSERT_ID()), 43543,3);
/****************************************************/




/*This is how you insert a charge*/
insert into `Charge` (`retailer_id`, `customer_id`,`state_code`,
`charge_date_time`)
  values ((select `retailer_id` from `Retailer` where `retailer_fname`='John'),
  (select   `customer_id` from `Customer` where `customer_fname`='Jimm'),34,(now()));

  /*This is how you retrieve a charge*/
  select * from `Charge` where year(`charge_date_time`) ='2011'
0 голосов
/ 15 сентября 2011
  1. Шаг 1 = Анализ требований (проведите аналитическое обсуждение с людьми, обладающими знаниями). Вы идентифицируете сущности (проще говоря, существительными обычно являются сущности: человек, клиент, поставщик и т. Д., А глаголами обычно являются отношения: работы, покупает, поставляет и т. д.) Такова цена субъекта (сомневаюсь в этом), является розничным продавцом (я держу пари на это) и т. д. Розничный продавец может быть субъектом, потому что он может существовать независимо, в то время как номер телефона не может существовать независимо, телефонномер - это что-то бессмысленное, если не связано с человеком!Клиент может существовать сам по себе, это имеет смысл!

  2. Другое дело (среди многих других) - спросить себя, о чем я собираюсь спросить базу данных,

    • Я попрошу цену, относящуюся только к штату или только к штату и году и т. Д.

Я должен остановить теорию здесь, потому что она становится слишкомбольшой, и поскольку теория не очень помогает, я сделаю несколько очень практических замечаний:

Отказ от ответственности

Имейте в виду, что я не осведомлен оанализ требований, поэтому я могу быть где-то совершенно не прав

  • Наличие главной таблицы, которая представляет сущность (такие таблицы без внешних ключей) о ценах ( способВы определяете это ) может быть плохой практикой, это может повредить вашей работе где-то.Это означает несоответствие , с плохим дизайном, неэффективным и т. Д. Допустимо, несоответствие НЕТ.Цены и ценности ... Я почти уверен, что нет такой вещи, как ценности, только цены!Поэтому дизайн, говорящий о цене 1, цене 2 и т. Д. Я считаю, что это не тот путь, если мы говорим о таблицах базы данных.

    • Имея таблицу на годы, ни за что!Год - это поле, это атрибут сущности, а не сущности!

    • Состояния, что вы имеете в виду под Нью-Йорком и т. Д., Иногда это поле.

  • Хорошо спроектированная таблица имеет первичный ключ (например, идентификатор клиента) или составной (например, идентификатор студента и идентификатор курса).В tbl_states_prices первое поле содержит идентификатор, мне кажется, этот идентификатор не только бесполезен, но также вводит в заблуждение и может быть вреден.возможно, вы сделали это, потому что некоторые внешние ключи могут быть пустыми, что означает плохой дизайн.

Фантастические системные требования и дизайн могут быть такими:

  1. Мы храним информацию о ритейлерах, поэтому ритейлер - это сущность с полями, такими как имя, местоположение, веб-сайт, штат (Нью-Йорк), телефон (обычно хранится во второй таблице, причина - это значение с несколькими вхождениями) и т. Д. Из скриншотов следует, чтоВы называете ритейлера клиентом.

tbl_retailer (retail_id, имя, фамилия и т. д.)

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

tbl_prices (retail_id, state, date, time)

все поля составляют составной первичный ключ!Там нет шансов, что у вас будут противоречивые записи таким образом.В вашем дизайне я мог бы ввести одну и ту же цену, для одного и того же клиента, одно и то же состояние миллион раз, и единственной разницей будет бессмысленный идентификатор (первое поле tbl_states_prices).Это все равно, что вставить миллион раз: 1. Джон Смит, отец женат и т. Д. 2. Джон Смит, отец женат и т. Д. .... 1000000. Джон Смит, отец женат и т. Д.

Насколько это последовательно, эффективно и т. Д.?!

Я удалил небольшую часть этого ответа, в новом ответе он улучшен.

0 голосов
/ 15 сентября 2011

Если вы хотите получить совет, я рекомендую вам использовать движок MyISAM в таблицах из-за высокой скорости выбора.Я использую InnoDB для таблиц с +1 миллионами строк, потому что мне нужно использовать ограничения внешних ключей, так что для mysql это ничего.

...