The most efficient way to store photo reference in

2019-07-19 11:44发布

问题:

I'm currently looking to store approximately 3.5 million photo's from approximately 100/200k users. I'm only using a mysql database on aws. My question is in regards to the most efficient way to store the photo reference. I'm only aware of two ways and I'm looking for an expert opinion.

Choice A

A user table with a photo_url column, in that column I would build a comma separated list of photo's that both maintain the name and sort order. The business logic would handle extracting the path from the photo name and append photo size. The downside is the processing expense.

Database example

"0ea102, e435b9, etc" 

Business logic would build the following urls from photo name

/0e/a1/02.jpg
/0e/a1/02_thumb.jpg 
/e4/35/b9.jpg
/e4/35/b9_thumb.jpg 

Choice B - Relational Table joined on user table with the following fields. I'm just concerned I may have potential database performance issues.

pk
user_id
photo_url_800
photo_url_150
photo_url_45
order

Does anybody have any suggestions on the better solution?

回答1:

The best and most common answer would be: choice B - Relational Table joined on user table with the following fields.

id
order
user_id
desc
photo_url_800
photo_url_150
photo_url_45
date_uploaded

Or a hybrid, wherein, you store the file names individually and add the photo directory with your business logic layer.

My analysis, your first option is a bad practice. Comma separated fields are not advisable for database. It would be difficult for you to update these fields and add description on it.

Regarding the table optimization, you might want to see these articles:

  • Optimizing MyISAM Queries
  • Optimizing InnoDB Queries


回答2:

Here is an example of my final solution using the hibernate ORM, Christian Mark, and my hybrid solution.

@Entity
public class Photo extends StatefulEntity {

    private static final String FILE_EXTENSION_JPEG = ".jpg";
    private static final String ROOT_PHOTO_URL = "/photo/";
    private static final String PHOTO_SIZE_800 = "_800";
    private static final String PHOTO_SIZE_150 = "_150";
    private static final String PHOTO_SIZE_100 = "_100";
    private static final String PHOTO_SIZE_50 = "_50";   

    @ManyToOne
    @JoinColumn(name = "profile_id", nullable = false)
    private Profile profile;

    //Example "a1d2b0" which will later get parsed into "/photo/a1/d2/b0_size.jpg"
    //using the generatePhotoUrl business logic below. 
    @Column(nullable = false, length = 6)
    private String fileName;

    private boolean temp;

    @Column(nullable = false)
    private int orderBy;

    @Temporal(TemporalType.TIMESTAMP)
    private Date dateUploaded;

    public Profile getProfile() {
        return profile;
    }

    public void setProfile(Profile profile) {
        this.profile = profile;
    }

    public String getFileName() {
        return fileName;
    }

    public void setFileName(String fileName) {
        this.fileName = fileName;
    }

    public Date getDateUploaded() {
        return dateUploaded;
    }

    public void setDateUploaded(Date dateUploaded) {
        this.dateUploaded = dateUploaded;
    }

    public boolean isTemp() {
        return temp;
    }

    public void setTemp(boolean temp) {
        this.temp = temp;
    }

    public int getOrderBy() {
        return orderBy;
    }

    public void setOrderBy(int orderBy) {
        this.orderBy = orderBy;
    }

    public String getPhotoSize800() {
        return generatePhotoURL(PHOTO_SIZE_800);
    }

    public String getPhotoSize150() {
        return generatePhotoURL(PHOTO_SIZE_150);
    }

    public String getPhotoSize100() {
        return generatePhotoURL(PHOTO_SIZE_100);
    }

    public String getPhotoSize50() {
        return generatePhotoURL(PHOTO_SIZE_50);
    }

    private String generatePhotoURL(String photoSize) {
        String firstDir = getFileName().substring(0, 2);
        String secondDir = getFileName().substring(2, 4);
        String photoName = getFileName().substring(4, 6);

        StringBuilder sb = new StringBuilder();
        sb.append(ROOT_PHOTO_URL);
        sb.append("/");
        sb.append(firstDir);
        sb.append("/");
        sb.append(secondDir);
        sb.append("/");
        sb.append(photoName);
        sb.append(photoSize);
        sb.append(FILE_EXTENSION_JPEG);
        return sb.toString();
    }

}